Game design mode-state machine mode

Source: Internet
Author: User

The state machine mode is a classic design pattern commonly used in a game, which is often used to deal with various states of a creature (such as walking, standing, jumping, etc.).

If we are developing an action game, the current task is to implement the behavior of controlling the protagonist based on the input--when the B key is pressed, he should jump.

Intuitive code:

    if (Input = = Press_b)        {if (!  m_isjumping) {            true;            Jump (); // Jumping Code         }    }

Later we need to add more behaviors, all of which behave as follows:

When standing press ↓ key = "Squat down."

When you squat down, press ↓ key = "stand."

When standing, press the B key = "Jump."

When jumping, press ↓ key = to trigger the dive.

    if(Input = =press_b) {        //If you are standing and you are not jumping, jump        if(!m_isjumping &&m_isstanding) {m_isjumping=true; Player.jump ();//Jumping Code        }    }    Else if(Input = =Press_down) {        //If you are jumping and are not diving, dive        if(m_isjumping &&!)m_isdiving) {m_isdiving player.dive ();//Dive The Code        }        //If you're not jumping ,        Else if(m_isjumping) {//if standing, then squat down            if(m_isstanding &&!)m_isjumping) {m_isstanding=false; Player.sneak ();//Squat down the code            }            //If you squat, stand            Else{m_isstanding=true; Player.stand ();//stand-up code            }        }    }

You can see that a bunch of if-else statements are very complex, and if you add more behavior, the logical structure is more difficult to maintain, and the code of the protagonist has to be recompiled (coupling is large)

Finite state machine

Finite state: A finite number of states.

One possible way is to encapsulate the behavior of these states && state transitions && states into classes,

such as

This time you can use the state machine design mode to beautify this code.

In the above scenario, there are only 4 states (jump/squat/stand/dive), which is a finite state.

So we designed the following 4 state classes (plus a state interface Class)

//state Interface ClassclassState { Public:    //processes the input and then transforms the corresponding state according to the input    Virtual voidHandleinput (player& Player,Constinput& input) =0;};//Standing StateclassStandstate: PublicState { Public:    voidHandleinput (player& Player,Constinput& input)Override{        if(Input = =press_b) {player.jump ();//code for character jumpsplayer.setstate (Jumpstate ()); }        Else if(Input = =Press_down) {player.sneak ();//Character Squat Codeplayer.setstate (Sneakstate ()); }    }};//Jumping StateclassJumpstate: PublicState { Public:    voidHandleinput (player& Player,Constinput& input)Override {        if(Input = =Press_down) {player.dive ();//code for character subductionplayer.setstate (Divestate ()); }    }};//Squat StateclassSneakstate: PublicState { Public:    voidHandleinput (player& Player,Constinput& input)Override {        if(Input = =Press_down) {Player.stand ();//character stand-up codeplayer.setstate (Standstate ()); }    }};//Dive StateclassDivestate: PublicState { Public:    voidHandleinput (player& Player,Constinput& input)Override {    }};

The first time you enter the game, give the character an initial state

Player.setstate (Standstate ());

Then each time you accept the input, let the character's current state object be processed.

Player.getstate (). Handleinput (Player,input);

Simple summary:

You can see that using state class objects, we encapsulate the responsible conditional logic into each state class, making the code elegant, and reducing the use of several variables (m_isjumping, etc.).

Also, because the properties of a finite state object are fixed, this means that all roles can share the same state (when the same state)

So the common way to store state objects is to store them either in a single case or in static storage (only 1 objects per state), avoiding the overhead of generating new state objects each time.

More improvements in finite state machines to improve parallel state machines

In practice, some game classes may require multiple states (parallel relationships), so you can write the following code

class player{    state * m_bodystate;   Physical state    state* m_equipmentstate;   Equipment Status     //..... other code };

You can then process the status in the following ways

void Player::handleinput (const input& Input) {    m_bodystate->handleinput (* This  , input);    M_equipmentstate->handleinput (*this, input);}
Level state Machine

After the protagonist's behavior is more figurative, it may contain a lot of similar states, in order to reuse the code, it will derive the concept of hierarchical state machine.

The main idea of the hierarchy state is the state class inheritance, which produces the state of the hierarchical relationship.

For example, squatting state and standing state inherit from the ground state.

classOngroundstate: PublicState {voidHandleinput (player& Player,Constinput& input)Override {        if(input = = Press_b) {}//.... Jumping    }};classStandstate: PublicOngroundstate {voidHandleinput (player& Player,Constinput& input)Override {        //when the ↓ key is released, squat down        if(input = = Release_down) {}//... Squat down the code ...        Else{ongroundstate::handleinput (player,input);} }};classSneakstate: PublicOngroundstate {//when the ↓ key is released, only stand up    if(input = = Release_down) {}//... Stand up the code ...    Else{ongroundstate::handleinput (player, input);}};

Push-down state machine

A push-down state machine, simply put, is to store a series of state objects with a stack structure.

In general, a role requires only one state object, why is it necessary to store a heap of state objects with a stack structure?

Assuming that there is a shooting game role, he is now standing in the top state of the execution stack.

Suddenly encounter the enemy to fire, then into the stack a fire state, and continue to execute the new stack top state.

The enemy was shot dead and the firing state ended. To revert to the previous state before firing, the top state of the stack is removed.

This way we use the stack to simulate the process of recovering a person's standing after firing.

In simple terms,

The push-down automata is suitable for state machines that require memory state, which is commonly used in some game AI. (But now the more popular game AI is implemented using the behavior tree)

Game design mode-state machine mode

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.