Swift-SpriteKit开发笔记(一)玩家状态机

【Swift-SpriteKit开发笔记(一)玩家状态机】什么是玩家状态机,这还要从状态机说起,通俗点说,就是主体在某个动作趋势下状态从A->B的转移,状态机刻画了状态集合和转移能力。在游戏中,玩家状态机代表玩家的状态转移规律,能够简洁的完成很多逻辑。
下面是一个简单的例子,玩家的状态包括以下六种:站立,跳跃,下落, 冲刺 ,走路, 着陆,在设计游戏代码逻辑和展示画面时,玩家的状态决定了精灵在场景中显示的贴图、交互和动画等,因此玩家状态机是游戏逻辑的核心,需要谨慎构建,才能打好地基,完善上层的丰富内容。
设计如下表格来表示状态转移,第i行第j列表示状态i能否转移到状态j,比如第二行第三列,从跳跃状态转移到下落状态为1,代表允许转移,第三行第二列,从下落状态转移到跳跃状态为0,表示禁止转移。

\ 站立 跳跃 下落 冲刺 走路 着陆
站立 0 1 0 1 1 1
跳跃 0 0 1 0 0 0
下落 0 0 0 1 0 1
冲刺 1 0 1 0 1 0
走路 1 1 1 1 0 0
着陆 1 0 0 0 0 0
用Swift实现玩家状态机的代码步骤如下:
  1. 构建状态类PlayerState,继承于GKState,设置绑定的玩家节点为成员变量
class PlayerState: GKState { unowned var playerNode: SKSpriteNode init(playerNode: SKSpriteNode) { self.playerNode = playerNode super.init() } }

  1. 构建六个具体状态类,继承于PlayerState,重载isValidNextState和didEnter两个函数。前者表示状态是否可以从当前状态转移过去的,就是说参数stateClass是否可以作为下一个状态;后者表示当进入到这个类对应的状态时,需要完成哪些操作。下面的代码是三个例子,作为跳跃、下落和着陆的状态类。
class JumpingState: PlayerState { override func isValidNextState(_ stateClass: AnyClass) -> Bool { switch stateClass { case is FallingState.Type: return true default: return false } }override func didEnter(from previousState: GKState?) { print("enter jumpingState") // 玩家对应跳跃的变化的动作或贴图变化 stateMachine?.enter(FallingState.self) } }class FallingState: PlayerState { override func isValidNextState(_ stateClass: AnyClass) -> Bool { switch stateClass { case is SprintState.Type, is LandingState.Type: return true default: return false } } override func didEnter(from previousState: GKState?) { print("enter FallingState") return } }class LandingState: PlayerState { override func isValidNextState(_ stateClass: AnyClass) -> Bool { if stateClass is StandState.Type{ return true } else { return false } }override func didEnter(from previousState: GKState?) { print("enter LandingState") stateMachine?.enter(StandState.self) } }

  1. 在GameScene中,添加GKStateMachine,与玩家节点绑定作为状态机,初始进入下落状态,开始随玩家交互和物理规律而转移状态。
playerStateMachine = GKStateMachine(states: [JumpingState(playerNode: knight), SprintState(playerNode: knight), StandState(playerNode: knight), WalkingState(playerNode: knight), FallingState(playerNode: knight), LandingState(playerNode: knight)]) playerStateMachine.enter(FallingState.self)

    推荐阅读