Tutorial details

Tutorial 5 - Finite State Machines | App Code for Sale | Preview

Tutorial 5 - Finite State Machines | iOS Tutorial

How to use Finite State Machine

Overview PAGE TOP

5.1 Introduction to Finite State Machines (FSM).

Just about every game includes some sort of Finite State Machine (FSM). It is the Developers go to structure for keeping track of what state the game is in and can be used to simulate intelligent behaviour. FSM's are popular because they are:

  • Simple to code;
  • Adaptable & flexible;
  • Easy to debug and maintain;
  • Quick; and
  • Easy to understand.

Even if you want to include some of the funkier game AI techniques like fuzzy logic or neural networks, FSM's form a solid foundation for the incorporation of these.

5.2 What is a FSM? PAGE TOP

FSM's were originally invented to solve mathematical problems. It is an abstract machine that can be in one of a finite number of states. The machine can only ever be in one state at a time which is called the current state. You need an event to occur to transition from the current state to a new state. A simple example of a FSM is a switch (see Figure 1). It has two states on and off. Transition from one state to another occurs when your finger flicks the switch. Note this is a European switch, in Australia they work the other way around (i.e. down for on and up for off).

Reefwing.5.2.png

5.3 Implementing a FSM. PAGE TOP

There are a number of different approaches to implementing a Finite State Machine. The easiest way is to use a series of if-then statements. We don't have a switch statement in Lua or enumerated types, so we can't use those.

In our Spacewar example we could add the following in our Main class setup() function. You need to have added the Twinkle class discussed in Interlude 5. This will simulate the game running portion of the game for now.

function setup()

    -- Keep track of Game State

    stateSplash = 0
    stateMenu = 1
    stateRun = 2
    stateWon = 3
    stateLost = 4

    gameState = stateSplash

    -- Create our menu button

    button = Button("    Start    ")
    button.action = function() buttonPressed() end

    -- Create the splash screen

    splashScreen = SplashScreen("Spacewar!", 10)

    -- Create the twinkling star background

    twinkleBackground = Twinkle(100)

end

And then in our draw() class, we could add:

function draw()

    -- Set background to black

    background(0, 0, 0)

    -- Draw the appropriate screen based on gameState

    if gameState == stateSplash then
        splashScreen: draw()
    elseif gameState == stateMenu then
        drawButton()
    elseif gameState == stateRun then
        twinkleBackground: draw()
    end

end

The drawButton() and touched(touch) functions are unchanged from the previous tutorial. Modify buttonPressed so that it looks like this:

function buttonPressed()

    -- If the menu button is pressed we transition to the next state.

    gameState = stateRun

end

Finally in the SplashScreen class you need to modify the fadeAnimationDone() function as follows:

function fadeAnimationDone()

    -- Call back function for Fader complete
    -- Splash screen done, transition to menu state

    gameState = stateMenu

end

And you are done, try it out. Your game is now operating as a Finite State Machine. The problem with this approach is that as your game gets more complex you can end up with spaghetti code, which is ok in the kitchen but not so good on the iPad.

5.4 Alternate Approach PAGE TOP

@aciolino over on the Codea Forums uses an alternate approach which we really like. We will let him explain in his own words...

Changing the GAMESTATE variable will immediately change the state of the app to whatever screen you want it to go to, all defined in the GAMESTATES table.

Note that this change is IMMEDIATE, so if you didn't set up some values in the destination screen, you're likely to get frustrated quickly. That's why I have a call to ScreenSplash:init() BEFORE I change the GAMESTATE variable.

Also, the screens that you redirect to WILL get the draw() and touched() calls, unlike the comments that Codea generates when you create a new class

--
-- Main.lua
-- 
-- Sample of Cofender's main()

function setup()

    displayMode(FULLSCREEN)
     -- define consts
    GAMESTATE_MENU = 1
    GAMESTATE_PLAYING = 2
    GAMESTATE_SHIPEXPLODE = 3
    GAMESTATE_LEVELCOMPLETE=5
    GAMESTATE_ENDED = 4
    GAMESTATE_SPLASH =6
    GAMESTATE_OPTIONS =7
    GAMESTATE_PAUSED = 8

    GAMESTATES = { ScreenTitle, ScreenGame, ScreenShipExplode, ScreenEnd, 
    ScreenLevelComplete, ScreenSplash, ScreenOptions , ScreenPaused }

    ScreenSplash:init()

    GAMESTATE = GAMESTATE_SPLASH 

end

-- This function gets called once every frame

function draw()
    -- This sets a dark background color 
    background(0, 0, 0, 255) 

    --state machine
    GAMESTATES[GAMESTATE]:draw()
end

function touched(touch)
    --state machine
    GAMESTATES[GAMESTATE]:touched(touch)      
end

--to send keys to proper screen for processing
function keyboard(key)
    GAMESTATES[GAMESTATE]:keyboard(key)      
end

Reference PAGE TOP

http://codeatuts.blogspot.in/2012/07/tutorial-5-finite-state-machines.html

0 Comments Leave a comment

Please login in order to leave a comment.

Newest first
!

Sign-in to your Chupamobile Account.

The Easiest way to Launch your next App or Game.

Join Chupamobile and get instant access to thousands of ready made App and Game Templates.

Creating an account means you’re okay with Chupamobile’s Terms of Service and Privacy Policy.