Is using a singleton the answer? - python

I'm trying to create a snips app to play songs using Python 3 and the python-vlc library. I am able to play my songs, but unable to stop them. The action will not run again while the song is playing, but other actions will, so I'm looking to put the stop function in a seperate file. The problem with this, is it creates a second instance of vlc and does not stop the current song.
I'm wondering if creating a singleton of the vlc object would allow me to accomplish this.
Does anyone have any recommendations?

In my opinion I think you can use Singleton for playing and pausing/stopping music.
It would make you able to control the only instance of the class that is initiated.
Especially if you only want to play small snippets of each song (kinda like SongPop I guess?), you'll be sure that no more than one instance of the class is initiated, and can be quite sure where and when it is used.

Related

Importing two python modules from each other

I have two modules one for the Main Menu lets call it MainMenu.py and another one for the game InGame.py, there is a button in each module that when clicked should take me to the other module:
NOTE: I always run MainMenu.py first then i open InGame using the button, I just need a way to go back to MainMenu.py then again back to a new ran InGame, I tried using classes for both modules but It didnt work because i have circular dependencies between other modules and InGame.py
# MainMenu.py
if button_clicked:
# run InGame.py
and
# InGame.py
if button_clicked:
#run MainMenu.py
I tried directly importing each module at first which obviously didnt work, it would take me from MainMenu to InGame, back to MainMenu and stops there, pressing the button in MainMenu wont do anything.
then I tried:
# MainMenu.py
if button_clicked:
if __name__ == "main":
import InGame
else:
del InGame
sys.modules.pop('InGame')
import InGame
and
# InGame.py
if button_clicked:
import MainMenu
But it also did nothing after going to MainMenu and trying to press the button to InGame, it just stops there.
I am sure this means my design is a mess but I even tried changing the whole design with no success so im looking for an easier fix.
I believe what you are trying to do is discouraged, there are a number of alternative approaches you can take which will remove the need for such cyclic references. The first immediate idea I have to solve your problem involves using an event driven design pattern. The general concept behind it is to have the MainMenu register an event that is called by your button. Your button does not need to know who is listening to the event but the main menu can still just as easily receive the message.
EDIT: The name was eluding me whilst typing the answer, its typically called the Observer Pattern.
When you run into problems like these, it generally indicates bad design, Its good that you were able to recognise that its a bit messy. I highly suggest looking into design patterns (if you dont know them already) even if they are in languages you dont know since the concept behind them is whats important.
In your case having something which mediates the flow between the two modules is the way to go, it will act as a parent in a sense and let you go between the two children

Is there a way to make a function wait for image to show up then clicking the image while on display using PyAutoGui (Python)

I'm currently making a BTD6 Auto Farmer what this means is that it will farm the game for me and click on the screen and play the game for me and complete the maps and stuff so I can get rewards that do not give me a competitive advantage because the game is single-player.
And to complete this bot I'd have to wait a certain amount of time and then see whenever a button shows up on the screen and to accomplish this I need to make a function that will wait for an image to show up on the screen and if the image shows up the function should press that image and that's all.
I tried many things and couldn't get it to work, here is my code that doesn't work:
def click_image(img):
x = pag.locateCenterOnScreen(img, confidence=config.OPENCV_CONFIDENCE)
pag.click(x)
This didn't work and I'm not surprised because the code creates the variable then tries pressing the variable there is no check or wait and I don't know how to implement that and that's what I'm asking for, that's the answer I'm looking for :)
It seems like you want to perform an asynchronous task, you should look into the python package asyncio.

Using opengl in pyglet to render 3d scene without event loop

Ok so I've spent an embarrassing amount of time on this problem and still am fairly confused. I'm hoping someone can provide some guidance, resources, similar projects, etc. I am unsure that what I am doing is the right way to go about this problem.
Background:
I am working on a project where I am developing an imitation of rocket league (a video game) so that I can run reinforcement learning algorithms on the game (I can't run the game itself because it would be too slow). The imitation needs to comply with OpenAI Gym's API, which essentially demands a step method (which takes in the actions the AI determines necessary at that timestep and outputs the state of the game after the timestep), and a render method. I have enough of the game implemented that I am currently working on the render method. I want to package this and release it on pypi, so I chose pyglet to implement the graphics because I read it is fairly portable.
Problem:
I don't think I can use an event loop to run my graphics. The way this api is set-up and used is that the user first instantiates the environment (the video game) and then sets up a loop in which they run the step function of the environment and optionally choose to also place the render method in that same loop depending on whether or not they want to see their AI's actions during that run. An example usage is available under environments on this page. So I can't use an event loop because it would stop execution of the user's loop. Instead I need to instantiate a window on the first call of render, and then update it with the state of the game on every subsequent call.
My current solution:
def render():
if self.window is None:
self.window = pyglet.window.Window(width, height)
self.window.clear()
self.window.dispatch_events()
... describe current 3d scence
self.window.flip()
Problem cont:
My current solution feels a bit hacky which I don't love, but more of a problem is that I can't figure out how to implement user input for this solution. I would like to be able to pan and move the camera all around the scene so that I view the 3-dimensional shape of objects, but I don't know how to implement that without the event loop and on_key_press decorator.
Also:
I am struggling to find good resources for 3d programming with OpenGL functions (the game is 3d). I was wondering if anyone knew of a good place to learn that without all complexity I found on https://learnopengl.com/. I don't even know if pyglet/opengl is the right way to go about solving this problem. I know very little about 3d graphics and am open to any suggestions.
So for anyone with a similar problem looking for the solution, here is what I determined:
If you need to render events but not give up control flow to pyglet.app.run() or any other event loop, custom or otherwise, it is possible to still listen for user actions. The following code is an example pseudo-implementation for a class that renders its state each time the render() function is called, with user input optionally changing that state. Be warned that this is far optimal from an efficiency perspective, and you should always use pyglet.app.run() when possible, but this instance demanded an alternative solution.
class Env:
# ...lots of other class stuff
def render(self):
if self.window is None:
self.window = pyglet.window.Window(width, height)
#self.window.event
def on_close():
self.window.close()
#self.window.event
def on_key_press(key, mod):
# ...do stuff on key press
pyglet.clock.tick()
self.window.clear()
self.window.dispatch_events()
# ...transform, update, create all objects that need to be rendered
self.window.flip()
env = Env()
for _ in range(100):
env.doStuff()
env.render()

Songs events in python game

I am trying to implement a game in python and i would like to have some effects songs in my game. I have done the following:
MusicStart.play()
MusicStart.stop()
I have assign all the details that needed. I want to play the song only one time. That i have done is repeated until the user press any input button.
Does someone know how to do it?
Not completely clear about your question, but here's what I did to implement music in my game (pygame):
pygame.mixer.music.load(os.path.join('.', 'path-to', 'your-music-file.wav'))
pygame.mixer.music.play(0, 0.0)
That way, the music file plays once only. Note that path-to would be the sub-folder you have the music files in (if you have one: if the file is in the same directory as the code, skip it) and your-music-file.wav would be your file, whether it's an .mp3, .wav, etc.
You can see the documentation page on it here.

Connect autonomous game model with Qt based UI

I've created a simple console based Scrabble game using Python. I tried to encapsulate the game model from the I/O as much as possible, meaning I created a few classes to describe the game with its rules and the current state. Basically I came up with these classes:
LetterSet: To describe the tiles in the game (score, total amount, etc.)
Board: A representation of the Board with its tiles and auxiliry functions
Player: A virtual class to subclass real Classes like Human or Bot, got one method play() which should return the players move
Game: Well ...
Everything works fine using a simple linear and synchronous flow with my console app.
But it turns out that its not that easy to port this concept to Qt. I've created all neccessary widgets like a Dragable board, general visual elements describing the game state and simple buttons like 'Pass', 'Continue', 'Exchange'.
The problem is, that I'm not sure how to handle the play() method which may use the Qt interface I created to generate a valid move. That's no problem for the Bot though, which simply searches a move without any interaction.
My current idea is to create a local event loop like described here and to wait for the buttons to get clicked in my play() method defined in Human(Bot). This is kinda ugly so I'm wondering if there is a better way to do it.
I would like the main logic to be the same e.g. the Player class serves a play() method which generates a move and returns it. This way it should be possible to create any type of Player's, like network players or bots. This synchronous way of doing it doesn't work very well with Qt's based signal/slot way of doing things. Hope someone got a neat idea to solve my problem.
Summarized: How to generate the Player's move inside its play() method and returning it like a simple move = player.play(game) call?
Edit: A snapshot to get an idea of what I'm talking about:
(source: b52 at reaktor42.de)
Edit2: This is rather old and I completed the assignment about two years ago successfully. Nevertheless I thought it might be useful for others if I publish the results through github.
Thanks in advance, Oli
What you can do in the Player play function is:
Enabled the buttons and connect them to slots (one per action)
Wait until the player move is validate (or any other reason to quit)
Disconnect signals to slot when the player move has been received (or is validated)
This is one way but you should modify it to fit your game model
My current idea is to create a local event loop like described here and to wait for the buttons to get clicked in my play() method defined in Human(Bot). This is kinda ugly so I'm wondering if there is a better way to do it.
I don't see why you think this is ugly. This is how practically any GUI program works: initialise a set of controls (buttons, etc), wait for the user to interact with the controls, respond to the interaction, and repeat.
I'd recommend you have a button for the player to submit their move. They click that, an event fires, the event handler tells your Player object that a move has been made and it passes it to the game logic event handler. The game logic checks whether the move is legal (you should put the code here rather than in the GUI classes), and passes control to the next Player object if the move was legal.
I think you're right that there's a bit of a disconnect between the event based model in a GUI environment and your original application design. With a console app you write the event loop, but in a GUI app in any of the frameworks I know, the framework has one of it's own.
I'd have the Player object send it's move via a signal to the game object. You would need to structure your base Player class around this design. It shouldn't all that hard to do as you've already got the actual logic worked out, you're just re-wiring it a bit.
Note that your Player objects are actually just interfaces between the game and the actual player which might be someone clicking buttons in the UI, or a remote player over a network connection. Only in the case of a bot can the player object actually be the player, and even in that case you might be best off having separate strategy engine objects. Thinking about it that way might help get a grip on the design.
You don't have to do it that way. You can work around it e.g. by the method you describe, but I wouldn't want to mess around with my own event loops inside an application that has it's own GUI event loop. That's fighting against the GUI framework rather than working with it. It's not just Qt that's like this, you'd have an issue similar to this in any GUI framework. It's a different way to think about structuring an application and I'd recommend embracing it.

Categories