AUFakie AUFakie -4 years ago 109
Python Question

Creating a state machine in python

I have created various simple 2 dimensional games in python before and because they were simple, I did not need to create such a thing. But I now need it due to needing to go back and fourth.
To go forward though, I need some sort of direction...

I am around 200 lines into a new game and I haven't started on the actual game, its currently all dealing with the window, events and state's

### state machine

def run:
#~setup window

# Current state
state = menu()

running = True
while running:
#~event handler

returns = state.update(events)
if returns == "playgame":
state = game()
state.draw(window)
#menu state
class menu:
def __init__(self):
#~define vars for the menu (buttons, etc...)
self.clickables = [] # filled with gui etc..
self.image = image() # image of the menu

def update(self, events):
for event in events: # go through events
for clickable in self.clickables: # go through clickables
if clickable.testClicked(event.pos) != False: # Returns if clicked
return clickable.testClicked(event.pos)

def draw(self, window):
self.image.draw(window)
#game state
class game(menu): # Exactly the same as menu (just used as example)
def __init__(self):
super(menu).__init__()
#gui button
class button: # Extremely shortened for example use
def __init__(self, do): # do is a string
self.whenClickedDo = do

def testClicked(self, mousePos):
if mousePos in self.myRect: # myRect is the area of the button (Example!)
return self.whenClickedDo
return False


This above example was completely rushed but the question I ponder is... What is a better way to achieve this, or is the above an achievable/smart way to do things?

TLDR; A function "run" has a value "state" which can return a value which would be used to change itself into a different state. Is that a reasonable way to make a state machine?

Answer Source

I wrote a simple game engine in C++ and used a screen based system. I'll try and write a simple version in python for you now. The idea is that each part of the game is a different screen. So the main menu, is a screen, there is a gameplay screen (where all the action takes place), there might be an options screen for the user to change the settings etc etc. These are all managed by a screen list, each screen has a position in the list, and you can switch between screens depending on game events. So if the main menu screen is active, when the user clicks the 'play' button, the gameplay screen is now loaded.

I cant think of the top of my head exactly how I'd port it to python but this should give you somewhere to start at least.

So a screen would be a class something like this:

class Screen:

    # you can have objects in the screen as variables of the class here
    # e.g self.player = None

    def onEntry(self):
        # here you would init the assets for your screen
        # this could be the interface, sprites etc
        # e.g self.player = Player()

    def onExit(self):
        # do any clean up
        # maybe save player data if this is a gameplay screen
        # e.g self.player.save()

    def update(self):
        # main loop for this screen
        # e.g self.player.update()

Each specific Screen for your game would inherit from the Screen class and implement those functions with custom logic for that screen. Then the screen list would basically just be a list of these custom Screen classes. Your game would just flip between these Screens.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download