状态模式是在我们游戏开发中非常常用的一个设计模式。状态模式的特点就是将状态和行为分离,每一个状态下只执行当前状态的行为,这样就将复杂的行为逻辑分为一个个不同状态下的行为逻辑,代码可维护性大大提高。
1.游戏的应用场景
玩家可以控制角色在场景中移动,攻击,飞行,静止不动或者被敌人攻击。在每一个状态下,玩家的动画是不一样的,并且在飞行状态玩家不能进行攻击,在受击状态下,玩家不能移动。
这就是典型的状态模式的需求——在不同的状态下有不同的行为模式。
上图是各个状态之间的转化,有了状态转化图,我们就可以着手开始写状态机的代码了,但在这之前我们先复习一下状态模式的基础内容。
2.状态模式
- StateM:用于维护和调度所有State
- State:状态的基类
- Idle/Run:这里画出了Idle和Run两个状态
这里我们只实现一个最基本的状态机,状态的转换会导致上一个状态结束(即调用leave),状态的进入会调用enter方法。pause方法被调用的情况是在当前状态进行切换,但状态并没有结束,只是产生了一个子状态,当子状态结束后,当前状态又会恢复(resume)。
class StateM(object):
def __init__(self):
self._states = {}
self._curr_state = None
def add_state(self, name, state):
self._states[name] = state
state.statem = self
def get_curr_state(self):
return self._curr_state
def call_method(self, method, *args, **kwargs):
curr_state = self.get_curr_state()
if curr_state and hasattr(curr_state, methed):
getattr(curr_state, method)(*args, **kwargs)
def change_to(self, name, *args, **kwargs):
if self._curr_state:
self._curr_state.leave()
self._curr_state = self._states[name]
self._curr_state.enter(*args, **kwargs)
StateM类change_to接口用于切换状态,call_method用于调用当前状态的方法。
class State(object):
def enter(self, *args, **kwargs):
pass
def leave(self):
pass
def pause(self):
pass
def resume(self):
pass
class Idle(State):
def enter(self):
super(Idle, self).enter()
# 播放待机动画
def play_fly(self):
self.statem.change_to("fly")
...
...
# main
self.statem = StateM()
self.statem.add_state("idle", Idle())
self.statem.add_state("fly", Fly())
self.statem.add_state("atk", Attack())
...
self.statem.change_to("idle")