Object state tracking techniques

I have a hero object that can be in many states and I am wonder what the best technique or at least a technique for handling them all.  Just to name a few: 

hero.isSpawning

hero.isRotating 

hero.isDead

hero.isCrazy 

hero.isSlow

hero.isInvinsible 

Game logic depends on these flags to determine what he can and can’t do.  For example, if he is rotating I prevent the gamer from moving him.  If he is spawning nothing can eat him etc…  But having all these flags gets confusing in the code and occasionally one of these flags gets stuck on and the game is all hung up.  Like he never completes rotating.   

I feel like I need a way to define allowable state transitions and then some kind of class that enforces these rules.  

I am sure this is a common problem that has been solved many times.   Would someone please point me to an example or two.   I saw some Java and Python ones on the internet but can’t really follow those since I am not a Java nor Python programmer.  

L

After some debugging I think I figured out what is causing the hang.  But since it is a timing window it is hard to tell for sure.  What I think is happening is this: 

My hero is left sideways on the screen by the gamer.  After a few seconds I start a transition to straighten him.  Since I want this to be subtle, the hero slowly moves for 4 seconds.   Just then a coin falls on him and he just happens to get enough energy to start the spawn process into a new and better hero.  This spawn process contains several transitions as he changes himself.  While in the middle of it the 4 second transition ends and appears to break my spawn transition process.  Then the hero is stuck mid-transform and the game is hung.   

I can’t find any doc on the web site the says what happens if you have 2 transitions going for one object.   In my case, it appears that the second callback never gets called.  Thus, breaking my spawning sequence.  

Again it is all about managing the hero’s state changes.  But I would like to know if you can have only one transition at a time going for an object.   It makes sense I guess.  

L

I feel like I need a way to define allowable state transitions and then some kind of class that enforces these rules.  

The computer science concept around this sort of thing is a finite state machine (often abbreviated FSM). This looks like a decent treatment, if you can get over the C++. I’ve not read this chapter myself, but can vouch for other parts of the book.

Of course, one could conceivably be crazy and invincible at the same time, to take two of your examples, so the “concurrent state machine” section is probably apt.

This hasn’t been updated in a while, but maybe it’s still good to go.

Even without building up a whole system, the basic idea is just swapping out the action that gets run, so even something like this might do:

local function Normal (player) -- whatever end local function Rotating (player) -- stuff end local function Crazy (player) -- stuff if CrazyTimeHasExpired() then player.action = Normal -- revert to normal state! end end -- more stuff MyPlayer.action = IsSpawning -- set some initial state Runtime:addEventListener("enterFrame", function() MyPlayer:action() -- do current action end)

In my own projects I like to use coroutines to do this, but that’s a matter of taste.

As for transitions, I don’t know if there’s any limit, but if they’re operating on the same properties they would end up fighting back and forth.

Competing transitions are no good, especially if they are complicated by delays.  Like @StarCrunch suggested, coroutines can help keep your transitions from overlapping.  

I suggest trying Erin Lin’s tweentrain plugin.  It’s free and it’s fabulous and it takes care for the transition coroutines for you.  You could also cancel all transitions on the hero before starting a new transition.  Use the parameter

[lua]

tag = “hero”

--------- example

transition.to(hero, {time = 1000, alpha = 1, tag = “hero”})

[/lua]

cancel any previous hero transitions with [lua]transition.cancel(“hero”)[/lua]

I have some AI experiments with hundreds of objects and it gets complicated really fast.  Writing any kind of AI, even simplified state machines, can really bloat your code with conditionals.  Here’s one way to handle it - nest your conditions:

[lua]

local hero = display.newCircle( 100, 100, 10 )

hero.isSpawning   = false

hero.isRotating   = false

hero.isDead       = false

hero.isCrazy      = false 

hero.isSlow       = false

hero.isInvinsible = false

local function heroAction( hero, action )

    if (hero.isDead == false) then

        if (action == “run” and hero.isSlow == false) then

            – run hero

        elseif (action == “focus” and hero.isCrazy == false) then

            – focus hero

        elseif (action == “die” and hero.isSpawning == false) then

            if (hero.isRotating) then

                – hero has a chance to escape death

            elseif (hero.isCrazy) then

                – gets a free shot at the enemy

                – hero dies

            else

                – hero dies

            end

        end

    end

end

heroAction(hero,“run”)

heroAction(hero,“focus”)

heroAction(hero,“die”)

[/lua]

I suggest working out the logic on paper with Venn Diagrams and flow charts before hammering out the logic in code.  Good luck!

Thanks guys, these are some really good ideas.  I will probably end up with some kind of combination.  My hero is a physics object but I also like to keep him pointed in the right direction using rotation.  Plus, he is a sprite which can dance, turnleft and right, wave,  etc.   So keeping all this in sync is quite the undertaking.  Thanks for the suggestions.   

After some debugging I think I figured out what is causing the hang.  But since it is a timing window it is hard to tell for sure.  What I think is happening is this: 

My hero is left sideways on the screen by the gamer.  After a few seconds I start a transition to straighten him.  Since I want this to be subtle, the hero slowly moves for 4 seconds.   Just then a coin falls on him and he just happens to get enough energy to start the spawn process into a new and better hero.  This spawn process contains several transitions as he changes himself.  While in the middle of it the 4 second transition ends and appears to break my spawn transition process.  Then the hero is stuck mid-transform and the game is hung.   

I can’t find any doc on the web site the says what happens if you have 2 transitions going for one object.   In my case, it appears that the second callback never gets called.  Thus, breaking my spawning sequence.  

Again it is all about managing the hero’s state changes.  But I would like to know if you can have only one transition at a time going for an object.   It makes sense I guess.  

L

I feel like I need a way to define allowable state transitions and then some kind of class that enforces these rules.  

The computer science concept around this sort of thing is a finite state machine (often abbreviated FSM). This looks like a decent treatment, if you can get over the C++. I’ve not read this chapter myself, but can vouch for other parts of the book.

Of course, one could conceivably be crazy and invincible at the same time, to take two of your examples, so the “concurrent state machine” section is probably apt.

This hasn’t been updated in a while, but maybe it’s still good to go.

Even without building up a whole system, the basic idea is just swapping out the action that gets run, so even something like this might do:

local function Normal (player) -- whatever end local function Rotating (player) -- stuff end local function Crazy (player) -- stuff if CrazyTimeHasExpired() then player.action = Normal -- revert to normal state! end end -- more stuff MyPlayer.action = IsSpawning -- set some initial state Runtime:addEventListener("enterFrame", function() MyPlayer:action() -- do current action end)

In my own projects I like to use coroutines to do this, but that’s a matter of taste.

As for transitions, I don’t know if there’s any limit, but if they’re operating on the same properties they would end up fighting back and forth.

Competing transitions are no good, especially if they are complicated by delays.  Like @StarCrunch suggested, coroutines can help keep your transitions from overlapping.  

I suggest trying Erin Lin’s tweentrain plugin.  It’s free and it’s fabulous and it takes care for the transition coroutines for you.  You could also cancel all transitions on the hero before starting a new transition.  Use the parameter

[lua]

tag = “hero”

--------- example

transition.to(hero, {time = 1000, alpha = 1, tag = “hero”})

[/lua]

cancel any previous hero transitions with [lua]transition.cancel(“hero”)[/lua]

I have some AI experiments with hundreds of objects and it gets complicated really fast.  Writing any kind of AI, even simplified state machines, can really bloat your code with conditionals.  Here’s one way to handle it - nest your conditions:

[lua]

local hero = display.newCircle( 100, 100, 10 )

hero.isSpawning   = false

hero.isRotating   = false

hero.isDead       = false

hero.isCrazy      = false 

hero.isSlow       = false

hero.isInvinsible = false

local function heroAction( hero, action )

    if (hero.isDead == false) then

        if (action == “run” and hero.isSlow == false) then

            – run hero

        elseif (action == “focus” and hero.isCrazy == false) then

            – focus hero

        elseif (action == “die” and hero.isSpawning == false) then

            if (hero.isRotating) then

                – hero has a chance to escape death

            elseif (hero.isCrazy) then

                – gets a free shot at the enemy

                – hero dies

            else

                – hero dies

            end

        end

    end

end

heroAction(hero,“run”)

heroAction(hero,“focus”)

heroAction(hero,“die”)

[/lua]

I suggest working out the logic on paper with Venn Diagrams and flow charts before hammering out the logic in code.  Good luck!

Thanks guys, these are some really good ideas.  I will probably end up with some kind of combination.  My hero is a physics object but I also like to keep him pointed in the right direction using rotation.  Plus, he is a sprite which can dance, turnleft and right, wave,  etc.   So keeping all this in sync is quite the undertaking.  Thanks for the suggestions.