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

Re: [pygame] State Machine Organization



In general, my State class has 5 important methods:

__init__ - the initializer, I don't do anything in it, other than take in parameters and store them.  In particular, I usually take in __init__(self,game,parent,other misc things...).  Thus I do my "stacking of states" manually on a per-case basis (by saving the parent).
.init() - automatically called before any other methods
.loop() - called once per frame to update logic stuff
.event(e) - called with evens as they become available
.paint(s) - called once per frame (or less, if I'm skipping frames) to render the scene

To change states, I just return a value from any of these states, and my "Engine" class will goto the next state.  (the game parameter above is an Engine instance .. which makes everything work and also servers as a "global" space)

Some extra methods I use in rare cases are:
.pause() - automatically called when I leave a state
.resume() - automatically called when I return to a state that was already .init()ed

Anyway, that's the basic gist... :)  Lately I've found more and more value in separating the model and the view - in terms of not wanting the model to contain any references to images or doing any rendering on its own.

Phil


Simon Oberhammer <simon.oberhammer@xxxxxxxxx> wrote:
Dave, what you describe sounds sensible to me. Until now I never worried about this kind of interface-stacking (never had many interface elements), but my MVC implementations should support what you describe without too much hassle.

But why are you referring to those screen instances as "states"? Or is this just to keep in tone with the thread?



On 7/7/07, Dave LeCompte (really) <dave@xxxxxxxxxxxx> wrote:
"Greg Ewing" < greg.ewing@xxxxxxxxxxxxxxxx> wrote:
> Kris Schnee wrote:
>> 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."
>
> This sounds similar to the way I've organised a couple of
> my recent PyGame entries. I have a Shell object at the top
> which implements the main loop. The Shell has an instance
> variable called current_screen which at any moment points
> to one of a number of different Screen subclasses which
> present different user interfaces. The Screen objects have
> methods for drawing the display, handling input events,
> etc.

I did something similar, sort of, for my most recent entry. Everything was
a "state", and I maintained a stack of states. Call this a Hierarchical
Finite State Machine, if you like. When I needed to interrupt a state to
pop up a dialog box (a good example was during my tutorial sequence), I'd
simply push a dialog box state onto my stack. When the dialog was done,
it'd pop itself off, and the old state would be the top of the stack.

Each state would implement OnDraw and OnUpdate events, with a few states
doing quasi-fancy things. For example, those dialog boxes would let their
parents draw first before drawing themselves, which gave the effect of
dialogs being "in front of" the main game screen. When I wanted to go back
to the main menu, I popped everybody off the stack, and pushed a new
instance of the main menu state onto the stack.

That worked pretty well for me, but I ended up keeping some data in the
state objects that probably belonged in a more intelligently encapsulated
place.

Thinking about MVC, this approach does separate out the logic (model) from
the display (view) - I didn't mention it above, but there's also
OnMouseDown and OnKeyDown which gets you the controller, as well. So I
didn't break up M/V/C into three separate classes, but each state object
had a pretty clean division of code.


If people are still looking for arguments in favor of separating out the
update logic from the display, there were two cases where it paid off in
my game:

- As I mentioned above, dialog boxes could be considered "child" states of
main gameplay states. By having the display of the parent state callable
without any update, I could suspend the progress of the game for a
temporary interruption (the "pause" menu that came up when you hit escape
or the window lost focus, tutorial dialog boxes, level intros).

- Having the game logic in one place, unentangled with display code made
it easier (after the challenge was over) to pull it out into a clean
location, so the AI could call it multiple times as a cheap form of
"lookahead". Rather than make the AI smart, it just simulated trying a
bunch of random options, and picked from the best results.


> (I'm going to have to write a wysiwig ascii-art drawing
> editor one day...)

I recently found out about emacs' "artist-mode", which seems just about
the level of quality that I'd need for ASCII art. I've even considered
(ab)using it as a level editor.

http://www.tulrich.com/geekstuff/emacs.html (look for artist-mode, towards
the bottom.)


I really gotta get back to working on my RPG.

-Dave LeCompte



Looking for a deal? Find great prices on flights and hotels with Yahoo! FareChase.