Connect autonomous game model with Qt based UI - python

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.

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

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()

Is using a singleton the answer?

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.

How can I extend a "normal" class with a static class in Python?

I'm using Python 3 and I'm trying to rewrite a graphics library that I wrote a while ago. Right now, I have a class called Scene which has three methods in addition to its constructor: logic(self), update(self), and render(self).
logic(self) handles the logic of each Scene. It handles all mouse and keyboard input, and figures out whether a button was clicked, et cetera.
update(self) can be thought of as an abstract method. Its contents are simply raise NotImplementedError. update(self) is called a certain number of times each second, and updates whatever is going on in the program, but does not draw anything on the screen. This is the framerate-independent update. If Pong were to be made with this library, the ball's position would be updated in this method.
render(self) actually updates the screen. This way, the speed of the program is not determined by the framerate.
I like my current implementation of Scene. It's really clean right now, and it seems very intuitive. However, I can't get over how to extend Scene. Suppose I want to make a Scene for a basic GUI like a main menu. I want there to be only one main menu Scene, because I don't think it's a good idea to recreate a whole other Scene every time the main menu will be viewed and used.
I started out by extending Scene with a static class, but quickly realized that it's not really possible to do that. Is the current paradigm just to extend Scene with a normal class, and then recreate and destroy it everytime that the subclass must be used? For example, should I just recreate and destroy a hypothetical MainMenu(Scene) object when viewing and leaving it, respectively?
Implement what the GoF refer to as Strategy Pattern, where you dynamically dispatch to appropriate logic based on current state.

How to handle button states efficiently in Tkinter

I've done a few searches but I couldn't find anything about this topic. Perhaps because it is common programmer knowledge (I'm not a programmer, I've learned from necessity), or because I'm going about it the wrong way.
I would like ideas/suggestions on how to manage button states for a GUI. For example, if I have a program which allows the user to import and process data, then certain functions should be inaccessible until the data has been imported successfully, or if they want to graph certain data, they need to select which data to graph before hitting the 'graph' or 'export' button. Even in the simple programs I've built these relationships seems to get complicated quickly. It seems simple to say "User shouldn't be able to hit button 'A' until 'B' and 'C' have been completed, then 'A' should be disabled if button 'D' or the 'Cancel' button. But that's a lot to track for one button. Thus far, I've tried two things:
Changing/Checking button states in the callback functions for the button. So in the above example, I would have code in buttons B's and C's callback to check if A should be enabled. And in buttons D's and Cancel's callbacks I would have code to disable button A. This gets complicated quickly and is difficult to maintain as code changes.
Setting boolean variables in every buttons callback (or just checking the states later using cget()) and checking the variables in a polling function to determine which buttons should be enabled or disabled.
I'm just not sure about this. I would like to make code as short and easy to understand as possible (and easy to edit later), but I don't like the idea of polling all the button states every few hundred milliseconds just for button 'management'. You can extend the same idea to check boxes, menu items, etc... but I'd like to here what others have done and why they do it the way they do.
You are only changing button states based on events, right? There is no reason to 'poll' to see if a button state has changed. What you can do is build a function which does all of the calling for you, then call it with something like disable_buttons([okButton, graphButton, printButton]). When an event takes place that modifies the appropriate user interface options (such as importing data), have another function that turns them on: enable_buttons([graphButton]). You could do this with each object's methods, of course, but making a wrapper allows you to be consistent throughout your application.

Categories