読者です 読者をやめる 読者になる 読者になる

しめ鯖日記

swift, iPhoneアプリ開発, ruby on rails等のTipsや入門記事書いてます

SwiftでStateパターンを実現できるGKStateMachineを試してみる

今日はGameplayKitのGKStateMachineというクラスを使ってみました。
こちらは簡単にStateパターンを実装できるクラスです。

Game用ライブラリであるGameplayKitに入ってはいるのですが、ゲーム以外のアプリを使う時にも使えそうです。

Stateパターンとは

Stateパターンとはオブジェクトの振る舞いをStateオブジェクトに持たせるデザインパターンです。
以下のサイトが非常に分かりやすかったので合わせて読んで頂くと理解が進むかと思います。

状態管理用の変数をインスタンスに持たせるなこのタコって話 - 猫型の蓄音機は 1 分間に 45 回にゃあと鳴く

GKStateMachineを使ってみる

GKStateMachineを使う際はGKStateMachineとGKStateの2つのクラスが重要になってきます。
GKStateはオブジェクトの振る舞いを書くクラスで、GKStateMachineはGKStateの切り替えや処理の橋渡しをするクラスです。

以下が実装例です。

import SpriteKit
import GameplayKit

class GameScene: SKScene {
    let user = User()
    var stateMachine: GKStateMachine?
    
    override func didMoveToView(view: SKView) {
        stateMachine = GKStateMachine(states: [
            RunningState(user: user),
            WalkingState(user: user),
            StoppingState(user: user)
            ]
        )
        stateMachine?.enterState(RunningState)
    }
    
    override func update(currentTime: CFTimeInterval) {
        stateMachine?.updateWithDeltaTime(0)
    }
}

class User {
    var point = CGPoint()
}

class MyState: GKState {
    let user: User
    
    init(user: User) {
        self.user = user
    }
}

class RunningState: MyState {
    override func updateWithDeltaTime(seconds: NSTimeInterval) {
        user.point.x += 10
        if 300 < user.point.x {
            stateMachine?.enterState(WalkingState)
        }
    }
}

class WalkingState: MyState {
    override func updateWithDeltaTime(seconds: NSTimeInterval) {
        user.point.x -= 5
        if user.point.x < 0 {
            stateMachine?.enterState(StoppingState)
        }
    }
}

class StoppingState: MyState {
}

実装例で何をしているか

実装例の仕様は以下の通りです。

  • pointプロパティーを持つUserオブジェクトいる
  • Userオブジェクトのxが300になるまではxが10ずつ増える
  • Userオブジェクトのxが300になったらxが0になるまで5ずつ減る
  • Userオブジェクトのxが0になったら停止する

簡単に言うとUserインスタンスが右に移動して左に移動して停止する処理を実装しています。