Help us understand the problem. What is going on with this article?

【GameplayKit】iOSゲームアプリにおけるStateパターン実践 Part_3

More than 1 year has passed since last update.

前回までの記事

【GameplayKit】iOSゲームアプリにおけるStateパターン実践 Part_2では、給水機が取りうる全ての状態に共通する機能が実装されたDispenserStateクラスを定義しました。

この記事について

本記事では、ステートとステートマシンの実装を行います。

給水機が変化しうるそれぞれの状態(ステート)を表現するクラスを定義します。
給水機は以下の状態に変化します。

  • 満タン(FullState)
  • 水あり(PartiallyFullState)
  • カラ (EmptyState)
  • 補給中(RefillingState)
  • 給水中(ServeState)

定義されたステートは、ステートマシンによって管理・操作します。
ステートマシンを使うことで、給水機そのものを操作するよりも効率的に給水機を扱うことができます。

手順

  1. FullStateクラスを定義
  2. ステートマシンを定義

満タン状態を表現するクラスを定義する

メニューバーから「File > New > File... > iOS > Swift File」を選択します。
ファイル名はFullState.swiftにしておきます。
SpriteKitGameplayKitフレームワークをインポートして、DispenserStateクラスを継承したFullStateクラスを定義します。

FullState.swift
import SpriteKit
import GameplayKit

class FullState: DispenserState {

}

親クラスに定義されているイニシャライザを利用して、必須イニシャライザを定義します。
また、didEnter(from:)メソッドとwillExit(to:)メソッドをオーバーライドします。

FullState.swift
class FullState: DispenserState {

    init(game: GameScene) {
        super.init(game: game, associatedNodeName: "FullState")
    }

    override func didEnter(from previousState: GKState?) {
        super.didEnter(from: previousState)

        let green = SKColor.green
        changeIndicatorLightToColor(green)
    }

    override func willExit(to nextState: GKState) {
        super.willExit(to: nextState)

        let black = SKColor.black
        changeIndicatorLightToColor(black)
    }

}

didEnter(from:)メソッドとwillExit(to:)メソッドでは、給水機の表示ランプの色を「満タンになったらグリーン・満タンではなくなったらブラック」に変化させています。

ステートマシンを定義する

ステートマシンは各種状態への遷移を管理する役割を持ち、GKStateMachineクラスによって表現されます。
ゲームシーンに、GKStateMachineクラスのオブジェクトを定義します。

まず、GameScene.swiftファイルにGameplayKitフレームワークをインポートしておきます。
メンバワイズプロパティにstateMachineプロパティを暗黙アンラップなオプショナルで定義します。
stateMachineプロパティは、didMove(to:)メソッドで初期化します。引数には、GKState型オブジェクトの配列を渡します。

GameScene.swift
import SpriteKit
import GameplayKit

class GameScene: SKScene {

    var stateMachine: GKStateMachine!

    override func didMove(to view: SKView) {
        let fullState = FullState(game: self)
        stateMachine = GKStateMachine(states: [fullState])

        stateMachine.enter(FullState.self)
    }

    override func didChangeSize(_ oldSize: CGSize) {
        let dispenser = childNode(withName: "dispenser")
        dispenser?.position.x = size.width / 2
    }

    override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
        let locationInView = touches.first?.location(in: view)
        let locationInScene = convertPoint(fromView: locationInView!)

        let refillButton = childNode(withName: "//refillButton")
        let location = locationInScene

        if atPoint(location) == refillButton {
            print("attempt to refill.")
        } else {
            print("attempt to dispense")
        }
    }
}

didMove(to:)メソッドで、給水機の初期状態がFullStateになるように記述しています。

ビルド

シミュレータでビルドしてみます。
給水機の表示ランプindicatorがグリーンになっていれば、状態がFullStateになっていることになります。また、状態遷移パネルにある「Full」がハイライトされていることも確認しておきましょう。

図. 満タン状態の給水機
スクリーンショット 2016-12-24 15.59.30.png

図. 満タン状態ではない給水機
スクリーンショット 2016-12-24 15.57.31.png

次回

ステートマシンを実現するGKStateMachineクラスを使って、状態GKStateオブジェクトを管理することができました。
ステートマシンでは、GKState型のインスタンスを操作せずにクラスそのものを扱っていることに注目できます。
次回【GameplayKit】iOSゲームアプリにおけるStateパターン実践 Part_4では、他の状態オブジェクトを定義して、状態から状態への繊維を実装します。

Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away