[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

Re: [pygame] State Machine Organization



Andre LeBlanc wrote:
I've spent the past 24 hours or so looking through the source for the PGU Engine and Phil's Pyweek3 example code, and its convinced me that I need to do alot of re-writing. I'm trying to figure out how to best organize the various states of my RPG, but I'm a little stuck. should a state be responsible for all of the rendering at a given time? for example in the case of a top-down RPG, Walking around town is a state, being in a battle is a state, but what about talking to an npc or a vendor in a town? This would have to bring up menus for the user to navigate, but the scenery in the town should still be painting. NPCs can walk around while you are talking to a shop owner, so should that be a separate state? I like the way the 'rooms' were subclassed and imported for the pyweek3 game and that's what I'm going for, but how would you transition between these 2 states, if indeed they should be separate.

The way I'm organizing the different states of my game is something like this. I've got a main Game class with a function called Notify, that takes messages from the interface or elsewhere. Then there are functions like WanderingScreen that set some overridden version of Notify and create one of several interface objects. Then there's a main loop that switches between the various "Screen" functions until one of them changes the Game object's state to "quit." Paraphrased code:

<code>
def WanderingScreen(self):
self.interface = WanderingScreen(screen=self.screen,pen=self.pen,input_pen=self.smallpen,parent=self)
    self.Notify = self.NotifyOnWanderingScreen
    done = False
    while not done:
        pass ## Do stuff

def Go(self):
    """This is the main loop of the game.

    Go between various screens until the game is over."""
    game_over = False
    while not game_over:
##print "Returned to main loop. Now switching to: "+str(self.game_state) function_to_call = self.functions_for_each_game_state.get(self.game_state)
        if function_to_call:
            function_to_call()
        else:
            game_over = True
    print "Game over. Thanks for playing!"

</code>

The idea is that instead of calling a shop screen from a walking-around screen, which risks having you get into some tangled recursion, the program "drops" from the walking screen back to the main loop, with a state variable saying "the next screen to go to is the shop screen."

So, adding a new screen to my game involves creating a new class of interface, adding a new version of the Notify function, and adding a Screen function to switch to. I was thinking lately that a simpler way to do this system would be to eliminate the different "Notify" functions and just do something like:

def Notify(self,message):
	self.messages.append(message)

And then the Screen functions could just read through their messages and process or ignore them however is appropriate.