天天看點

狀态機的實作

現在很多人在利用比較流行的開源遊戲引擎cocos2d-x開發遊戲,在遊戲中免不了使用狀态機,這裡給大家一種我自認為好的狀态機的實作O(∩_∩)O~。

先貼上代碼:

#ifndef BASESTATE_H
#define BASESTATE_H


template <class entity_type>
class BaseState
{
public:
	//BaseState(void){};
	virtual void Enter(entity_type*)=0;
	virtual void Execute(entity_type*)=0;
	virtual void Exit(entity_type*)=0;
	virtual ~BaseState(void){};
};


#endif // !BASESTATE_H
           

以上為狀态類代碼,O(∩_∩)O~。簡單的隻有 三個主要調用的函數,進入,執行,離開。

然後我們繼續檢視下狀态機的基類,廢話不多說,先上代碼,這樣新手可以直接拿走直接使用。、

#ifndef BASESTATEMACHINE_H
#define BASESTATEMACHINE_H
//
// 
/// @file	狀态機基類
/// @brief	負責狀态機的跳轉
/// @version 2.0
//
#include "BaseState.h"
#include <assert.h>
//
/// @class BaseStateMachine
/// @brief 狀态機基類
///
/// \n本類負責模闆狀态機的所有處理
template <class entity_type>
class BaseStateMachine
{
private:
	entity_type *m_pOwner;						///<指向擁有這個了執行個體的智能體的指針

	BaseState<entity_type>	*m_pCurrentState;	///<智能體的目前狀态

	BaseState<entity_type>	*m_pPreviousState;	///<智能體的上一個狀态

	BaseState<entity_type>	*m_pGlobalState;	///<每次FSM被更新時,這個狀态被調用

public:
	BaseStateMachine(entity_type* owner):
		m_pOwner(owner),
		m_pCurrentState(nullptr),
		m_pPreviousState(nullptr),
		m_pGlobalState(nullptr)
	{

	}
	
	///@brief 設定目前狀态
	///@param [in]s 要設定的狀态
	///@return 無傳回值
	
	void SetCurrentState(BaseState<entity_type> *s)
	{
		m_pCurrentState = s;
	}
	
	///@brief 設定全局狀态
	///@param [in]s 要設定的狀态
	///@return 無傳回值
	
	void SetGlobalState(BaseState<entity_type> *s)
	{
		m_pGlobalState = s;
	}
	
	///@brief 設定前面的狀态
	///@param [in]s 要設定的狀态
	///@return 無傳回值
	
	void SetPreviousState(BaseState<entity_type> *s)
	{
		m_pPreviousState = s;
	}
	
	///@brief 更新狀态
	///
	///@return 無傳回值
	
	void Update()const
	{
		if (m_pGlobalState)
		{
			m_pGlobalState->Execute(m_pOwner);
		}

		if (m_pCurrentState)
		{
			m_pCurrentState->Execute(m_pOwner);
		}
	}

	
	///@brief 改變狀态
	///@param [in]s 要設定的狀态
	///@return 無傳回值
	
	void ChangeState(BaseState<entity_type> *pNewState)
	{
		//assert(PNewState && "<BaseStateMachine::ChangeState>:trying to change to a null state");

		///保留前一個狀态記錄
		m_pPreviousState = m_pCurrentState;
		///調用現有狀态的退出方法
		m_pCurrentState->Exit(m_pOwner);
		///改變到一個新狀态
		m_pCurrentState= pNewState;
		///調用新狀态的進入方法
		m_pCurrentState->Enter(m_pOwner);
	}
	
	///@brief 改變到上一狀态
	///
	///@return 無傳回值
	
	void RevertToPreviousState()
	{
		ChangeState(m_pPreviousState);
	}
	
	///@brief 檢視目前狀态
	///
	///@return BaseState<entity_type>*目前狀态
	
	BaseState<entity_type>* CurrentState() const
	{
		return m_pCurrentState; 
	}

	
	///@brief 檢視全局狀态
	///
	///@return BaseState<entity_type>* 全局狀态
	
	BaseState<entity_type>* GlobalState() const
	{
		return m_pGlobalState; 
	}
	
	///@brief 檢視前一狀态
	///
	///@return BaseState<entity_type>*前一狀态
	
	BaseState<entity_type>* PreviousState() const
	{
		return m_pPreviousState; 
	}
	  //class passed as a parameter. 
	bool  isInState(const BaseState<entity_type>& st)const
	{
		return typeid(*m_pCurrentState) == typeid(st);
	}
};


#endif // !BASESTATEMACHINE_H
           

這個是狀态機的基類,使用的時候隻需要在每個具體執行個體中申明一個狀态機的類,然後完成自己的狀态類的填寫,即可完成一個高品質的狀态機。注釋很全有中文的也有英文的,有興趣的童鞋可以讨論下這個設計是否合理。