state模式实现游戏动画系统

在游戏中,游戏人物根据玩家的输入以及人物与游戏世界交互,会有许多动作动画效果的转换。简单的比如马里奥,玩家没有输入,没有发生游戏事件(吃到蘑菇、碰到怪物)时,马里奥大叔静止不动。玩家按下移动按钮,马里奥开始走动,这时需要绘制走路的动画效果。按下跳跃键,绘制跳跃的动画效果。而按键和动作并不是一一对应的关系,比如跳跃过程中按下左右移动键,并不能绘制走路的动画效果。

 

这些状态之间的转换可以使用if else,switch case,语句来完成,如下:

//这里把人物写成一个Role类
class Role
{

public:

enum STATE
{
IDLE,
WALK,
JUMP,
}

void JumpInput()
{
	_state = JUMP;
	//..设置当前动画为跳跃的动画
}

void WalkInput()
{
	if (_state == IDLE)
	{
		_state = WALK;
		//..设置当前动画为行走的动画
	}
}

// 跳跃后角色落地,由碰撞检测触发
void OnLand()
{
	 _state = IDLE;
}
private:

STATE _state;

}
 

貌似挺完美,嗯,这样完美的情况仅仅只限于状态比较少,状态转换比较简单的条件下,如果人物状态一增多,状态转换条件一变复杂,那将变成一场噩梦,代码中会产生大量的if else条件判断,比如我们再增加一个蹲下的状态,蹲下时按下跳跃键让游戏人物快速向前贴地滑动一段距离,Rockman的操作好像就是这样。再加一个约束条件,蹲下时按下左右移动键无效果。哇哦,这样再看看上面那段简单的代码要变成什么样子了。

 

如何以一种条理清晰,便于维护的方式来实现以上需求呢? 以上需求的核心是状态的转换,自然而然,带有“状态”这个关键字的state模式首先成了思考方向。state模式将每个状态抽象成类,状态的转换由状态自己来操作,是一种比较灵活的实现方式。基于state模式,将代码重构如下(伪代码):

// 伪代码
class IStatus
{
	Role* role;
	// 输入向上键
	virtual void Up();
	// 输入向下键
	virtual void Down();
	// 输入向左键
	virtual void Left();
	// 输入向右键
	virtual void Right();
	// 输入跳跃键
	virtual void Jump();
	// 输入攻击键
	virtual void Attack();
	// 动作完成后
	virtula void Done();
};

class IdleState;
{
	Left() {role->setState(WalkState);}
	Right() {role->setState(WalkState);}
	Down() {role->setState(CrouchState);}
	Jump() {role->setState(JumpState);}
}

class WalkState
{
	Jump() {role->setState(JumpState);}
}

class JumpState;
{

}

class CrouchState
{
	Jump() {role->setState(SlipState);}
}
class SlipState
{

}
 
Role类:
class Role
{	
	IState _state;
	// 输入向上键
	void Up() { _state.Up();}
	// 输入向下键
	void Down() { _state.Down();}
	// 输入向左键
	void Left() { _state.Left();}
	// 输入向右键
	void Right() { _state.Right();}
	// 输入跳跃键
	void Jump() { _state.Jump();}
	// 输入攻击键
	void Attack() { _state.Attack();}
}
 
这样用state模式来写,后期维护和加入新的状态也变得十分容易,加入新的状态只需要加入一个新的类,而不需变更以有的代码。
posted @ 2011-08-13 01:10  火月  阅读(301)  评论(0编辑  收藏  举报