游戏中的状态机

Game Develop Diary

Posted by Francis-wu on July 17, 2018

随便写点和游戏有关的设计模式感悟,本篇关于状态机(state)。state用途非常广,用来做某一类的行为管理非常方便。比如人物的移动状态:飞行、走路、奔跑、骑马,再比如相机的模式,聊天、拍照、3D、2D。这些状态都有一些共性,又有各自独立的逻辑,我们不可能到处switch case,各自的状态里处理自己的事情,外面用一个管理器来管理这些状态的进入、离开、刷新,所以就产生了state设计模式。(任何问题欢迎邮件:admin@franciswu.top

state设计模式简单实现

#include <iostream>
#include <map>
using namespace std;

enum StateIndex
{
	STATE_INDEX_NULL = 0,
	STATE_A,
	STATE_B,
	STATE_MAX,
};

class state
{
public:
	state(){};
	virtual ~state(){};

	virtual void entry() = 0;
	virtual void leave() = 0;
	virtual void print() = 0;

};

class stateA :public state
{
public:
	stateA():state(){};
	virtual ~stateA(){};

	virtual void entry();
	virtual void leave();
	virtual void print();
};

void stateA::entry()
{
	cout<<"进入状态A"<<endl;
}

void stateA::leave()
{
	cout<<"离开状态A"<<endl;
}

void stateA::print()
{
	cout<<"处于A状态"<<endl;
}

class stateB :public state
{
public:
	stateB():state(){};
	virtual ~stateB(){};

	virtual void entry();
	virtual void leave();
	virtual void print();
};

void stateB::entry()
{
	cout<<"进入状态B"<<endl;
}

void stateB::leave()
{
	cout<<"离开状态B"<<endl;
}

void stateB::print()
{
	cout<<"处于B状态"<<endl;
}

class StateController
{
public:
	StateController();
	~StateController();

	bool StateInit();
	bool StateSwitch(int iStateIndex);
	
	void print();

private:
	typedef std::map<int, state*> StateMap;
	StateMap m_StateMap;

	state* m_state;
};

StateController::StateController()
{
	m_state = NULL;
}

StateController::~StateController()
{
	StateMap::iterator it = m_StateMap.begin();
	for (; it != m_StateMap.end(); ++it)
	{
		state* pState = it->second;
		if (pState != NULL)
		{
			delete pState;
			it->second = NULL;
		}
	}
}

bool StateController::StateSwitch(int iStateIndex)
{
	StateMap::const_iterator c_it = m_StateMap.find(iStateIndex);
	if (c_it != m_StateMap.end())
	{
		if (m_state != NULL)
		{
			m_state->leave();
		}

		m_state = c_it->second;
		if (m_state != NULL)
		{
			m_state->entry();
		}
	}

	return true;
}

bool StateController::StateInit()
{
	m_StateMap.insert(make_pair(STATE_A, new stateA()));

	m_StateMap.insert(make_pair(STATE_B, new stateB()));

	return true;
}

void StateController::print()
{
	if (m_state != NULL)
	{
		m_state->print();
	}
}

int main()
{
	StateController controllerTest;

	//初始化状态
	controllerTest.StateInit();

	controllerTest.StateSwitch(STATE_A);

	controllerTest.print();

	controllerTest.StateSwitch(STATE_B);

	controllerTest.print();

	system("pause");

	return 0;
}

实现起来很简单,也有很多方法,主要是要去习惯这种思路,很多东西都可以通过一种状态来进行管理,每个状态的处理本状态的事件(结合command模式)。

游戏中的使用

可以通过状态机来管理很多常见的游戏行为,比如人物行为,相机行为,简单AI,到目前为止接触过最有意思的是人物行为的管理。

对于多人在线游戏来说,同样的行为在不同玩家的客户端上处理是不一样的,简单来说,本客户端操作的主玩家在行走的时候,进入motion状态,而其他玩家客户端看到的我则会进入bemotion状态,主客户端处理motion下的行走,跳跃,转向,然后通过服务器将移动消息同步给其他客户端,其他客户端在bemotion中进行处理。