Application of finite state machine in game

Source: Internet
Author: User
Tags fsm

Games often have a variety of AI behavior, such as the monster cut people, players and so on automatic hanging machine. Suppose there is such a simple scenario

A monster in the scene usually patrols at the mouth of the cave. When encountering an enemy, if it is stronger than the other, beat the enemy, if weaker than the enemy, then bypass the escape.

Using the switch or if statement, it is easy to achieve the above requirements

Enum State {
    Patrol,
	Runaway,
	Attack
};

void OnUpdate (state currstate) {
	
	switch (currstage) {case
		Patrol: {
			if (Seeenemy ()) {
				if ( Strongerthanenemy) {
					changestate (Attack);
				} else {
					changestate (runaway);
				}
			}
			break;
		Case Attack: {
			//fast die
			if (Willdiesoon ()) {
				changestate (runaway);
			} else {
				if (Enemydie ()) { C22/>changestate (Patrol);
				}
			break;
		Case runaway: {
			if (Safenow ()) {
				changestate (Patrol);
			}
			break;
		}}}

At first glance, it's reasonable to achieve this. But in practical applications, this code becomes a nightmare if it encounters a state of complexity.

There are two simpler ways to implement the game AI. One is the behavior tree, also called the decision tree. The other is the method we are going to talk about today, the finite state machine.

A finite state machine is an intelligent body with a finite number of states. To accept certain events in a given state, you can switch from one state to another state. A finite state machine that can only be in one state at any time.

The simplest state machine can be understood by the light switch. There are two states of light, on or off. In the open state to accept the Click event, will be cut to the closed state, in the state of the switch to accept the Click event, will be switched to open state.


State Transformation Table

One way to organize and influence state transitions is to develop a state transformation table.


In the design of AI, it is important to understand the state of the transformation process, otherwise it is easy to make the agent into a certain state and can not go out.


Here we use the "state mode" in the design pattern to implement the code for the finite state machine.

For each state, we need at least three methods.

Public interface State {
	
	/**
	 * Switch to New status
	 * @param creature
	/void OnEnter (creature creature);
	
	/**
	 * Leave the current state
	 * @param
	 creature
	/void OnExit (creature creature);
	
	/**
	 * Every tick running business
	 * @param creature
	/void execute (creature creature);

}
Gives a state implementation of an attack, with other status codes similar

public class Attackstate implements state {

	@Override public
	void OnEnter (creature creature) {
		//Enter attack status
		
	}

	@Override public
	void OnExit (creature creature) {
		//Leave attack State
	}

	@Override public
	void Execute ( Creature creature) {
		player player = (player) creature;
		Scene Scene = Player.getscene ();
		Monster Monster = Scene.getmonster ();
		PLAYER.CHANGEHP (-monster.getattack ());
		MONSTER.CHANGEHP (-player.getattack ());
		System.err.println ("Meet the enemy, quickly use a double-cut stick, hum ha xi." "
				+" Our blood quantity ["+ PLAYER.GETHP () +"] "
				+" enemy blood volume ["+ MONSTER.GETHP () +"] ");

	}

State switching rules (transition abstract classes) require binding start and end states, and abstract methods to determine whether the agent can be converted in its current state.

Public abstract class Transition {

	/** start state * * from
	;
	/** End Status *
	/private state to;
	
	Public Transition {
		this.from = from;
		This.to = to;
	}
	
	/** *
	 Condition Determination
	 * @param creature
	 * @return
	/Public Abstract Boolean meetcondition (creature creature);

	Public State fromstate () {return
		this.from;
	}
	
	Public State tostate () {return
		this.to
	}}
	
gives a state of implementation, other code similar to

public class Attack2runtransition extends Transition {public

	attack2runtransition
		Super (from, to);

	@Override Public
	Boolean meetcondition (creature creature) {
		//If you are currently in an attack state and have a lower damage than a monster, then run for your escape
		Player Player = (player) creature;
		Scene Scene = Player.getscene ();
		return  PLAYER.GETHP () < 	//dying
				| | player.getattack () > Scene.getmonster (). Getattack (
				) | | Math.random () < 0.4	;//probability of escape, increase random event
	}

}
Finite state machine (Agent business performer)

public class Finitestatemachine {private state initstate;
	Private State currstate;
	/** various states and corresponding conversion rules * * Private map<state, list<transition>> state2transtions = new hashmap<> ();
	/** in order to support AI pause * * Private volatile Boolean running = true;

	/** Recovery AI Timeout time * * Private long freezetimeout; public void Addtransition (Transition Transition) {list<transition> transitions = state2transtions.get (
		Transition.fromstate ());
			if (transitions = = null) {transitions = new arraylist<> ();
		State2transtions.put (Transition.fromstate (), transitions);
	} transitions.add (transition);
	Public State getinitstate () {return initstate;
	public void Setinitstate (state initstate) {this.initstate = initstate;
			public void Enterframe (creature creature) {if (this.currstate = = null) {this.currstate = this.initstate;
		This.currState.onEnter (creature);
		} set<string> passed = new hashset<> (); String Clazzname = this.currState.geTclass (). GetName (); for (;;) {if (!running) {if (freezetimeout > 0 && system.currenttimemillis () > Freezetimeout) {runnin
				G = true;
				} else {break;
			} this.currState.execute (creature);
			if (Passed.contains (Clazzname)) {break;

			} passed.add (Clazzname);
			list<transition> transitions = state2transtions.get (this.currstate); for (Transition transition:transitions) {if (transition.meetcondition (creature)) {This.currState.onExit (Creatur
					e);
					This.currstate = Transition.tostate ();
				This.currState.onEnter (creature); /** * Suspend AI * @param timeout */public void freeze (long timeout) {this.freezetimeout = System.c
	Urrenttimemillis () + timeout; }

}
Sample code

public class Aitest {public static void main (string[] args) throws Exception {player player = new player (100, 15);
		
		Monster Monster = new Monster (120, 10);
		Scene Scene = new Scene ();
		Scene.setplayer (player);
		
		Scene.setmonster (Monster);
		Player.setscene (Scene);
		
		Monster.setscene (Scene);
		state patrolstate = new Patrolstate ();
		state attackstate = new Attackstate ();
		
		state runstate = new Runawaystate ();
		Transition transition1 = new Patrol2attacktransition (patrolstate, attackstate);
		Transition transition2 = new Attack2runtransition (attackstate, runstate);
		Transition Transition3 = new Atttack2patroltransition (attackstate, patrolstate);
		
		Transition transition4 = new Run2patroltransition (runstate, patrolstate);
		Finitestatemachine FSM = new Finitestatemachine ();
		
		Fsm.setinitstate (patrolstate);
		Fsm.addtransition (Transition1);
		Fsm.addtransition (Transition2);
		Fsm.addtransition (Transition3);
		
		Fsm.addtransition (TRANSITION4);
while (true) {			Fsm.enterframe (player);
		Thread.Sleep (500); }
			
		
	}

}
Code run results (limited to space, some screenshots are not visible)


Additional auxiliary Code

Biological Class (creature), the player and the monster of the parent class

Public abstract class Creature {
	
	protected long hp;
	
	protected int attack;
	
	Private Scene Scene;

	Public creature (long hp, int attack) {
		this.hp = hp;
		This.attack = attack;
	}

	Public long GETHP () {return
		hp;
	}

	public void Sethp (long hp) {
		this.hp = hp;
	}
	
	public void changehp (long changehp) {
		this.hp + = CHANGEHP;
	}

	public int Getattack () {return
		attack;
	}

	public void Setattack (int attack) {
		this.attack = attack;
	}
	
	Public Scene Getscene () {return
		Scene;
	}

	public void Setscene (Scene Scene) {
		this.scene = Scene;
	}
	
	public Boolean Isdie () {return
		this.hp <= 0;
	}

}
Player class. Monster class is similar to it, change a name
Public class player extends creature {public
	

	player (long hp, int attack) {
		super (HP, attack);
	}

	@Override public
	String toString () {return
		"Player [hp= + hp +", attack= "+ attack +]";
	}
	
}
Scene class

public class Scene {
	
	private player player;
	
	Private Monster Monster;

	Public player Getplayer () {return
		player;
	}

	public void Setplayer (player player) {
		this.player = player;
	}

	Public Monster Getmonster () {return
		Monster;
	}

	public void Setmonster (Monster Monster) {
		this.monster = Monster;
	}

}

 layered finite state machine

If a state itself is made up of a small system, we can use a layered finite state machine (hierarchicalfinitestatemachine) for ease of management. For example, the attack status can be subdivided to track enemy-> selection skills-> combat. It's not going to start here.













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.