2017年8月23日水曜日

SpriteKit を使って画面遷移する方法

概要

シングルページビューアプリケーションなどは Storyboard を使って Segue で画面遷移を UIView 同士をつなぐことで画面遷移を実現します
SpriteKit も SKView の親クラスが UIView なので Segue も使えるのですが、ちょっとややこしいです
SpriteKit の場合はシーンファイルを変更することで画面遷移を実現することができます

環境

  • macOS X 10.12.6
  • Xcode 8.3.3 (8E3004b)

遷移元と遷移先のシーンファイルを作成する

何でも OK です
.sks ファイルと .swift ファイルを作成しましょう

  • File -> New -> File -> SpriteKit Scene
  • File -> New -> File -> Swift File

で今回は FirstScene.sks と FirstScene.swift および SecondScene.sks と SecondScene.swift および を作成しました
作成した .sks ファイルの Scene の Custom Class にそれぞれ FirstScene.swift と SecondScene.swift を設定しましょう

そして画面に遷移するボタンの SKSpriteNode を追加しましょう
このノードをタップしたら別のシーンに遷移するようにします
spritekit_scene_change1.png

.sks ファイルはこんな感じになっていれば OK です
SecondSecne.sks も同様にノードと Custom Class を設定すれば OK です

.swift ファイルの編集

.sks ファイルに配置したノードを Swift 側で扱いましょう
FirstScene.swift は以下のようになります

  • FirstScene.swift
import SpriteKit

class FirstScene: SKScene {

    // second ボタン
    var second = SKSpriteNode()

    override func didMove(to view: SKView) {
        // second ボタンの初期化
        second = self.childNode(withName: "second") as! SKSpriteNode
    }

    func touchDown(atPoint pos : CGPoint) {
        if let node = atPoint(pos) as? SKSpriteNode {
            if(node == second){
                if let view = self.view {
                    if let scene = SecondScene(fileNamed: "SecondScene") {
                        scene.scaleMode = .aspectFill
                        view.presentScene(scene)
                    }
                    view.ignoresSiblingOrder = true
                    view.showsFPS = true
                    view.showsNodeCount = true
                }
            }
        }
    }

    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        for t in touches { self.touchDown(atPoint: t.location(in: self)) }
    }
}

まず .sks ファイルで定義したノードを childNode で取得します
そして touchesBegan -> touchDown メソッドでタッチを判定します
もしタッチした箇所のノードが遷移用のノードだった場合は SecondScene を作成して view.presentScene で画面遷移させています

その後の showsFPS はデバッグ用に表示しているだけなので不要であれば削除してください

これとほぼ同じことを SecondScene.swift でも実装すれば OK です

  • SecondScene.swift
import SpriteKit

class SecondScene: SKScene {

    // first ボタン
    var first = SKSpriteNode()

    override func didMove(to view: SKView) {
        // first ボタンの初期化
        first = self.childNode(withName: "first") as! SKSpriteNode
    }

    func touchDown(atPoint pos : CGPoint) {
        if let node = atPoint(pos) as? SKSpriteNode {
            if(node == first){
                if let view = self.view {
                    if let scene = FirstScene(fileNamed: "FirstScene") {
                        scene.scaleMode = .aspectFill
                        view.presentScene(scene)
                    }
                    view.ignoresSiblingOrder = true
                    view.showsFPS = true
                    view.showsNodeCount = true
                }
            }
        }
    }

    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        for t in touches { self.touchDown(atPoint: t.location(in: self)) }
    }
}

動作確認

では動作確認してみます
spritekit_scene_change2.gif

こんな感じでノードをタップしたときに画面遷移すれば OK です

最後に

SpriteKit で画面遷移を実現してみました
UIKit を使った場合の実装方法とは少し異なりますが慣れれば簡単にできます
他に UIKit と違う点をざっと上げると

  • NavigationController を使っていないので画面端のスワイプでは元の画面にもどれない
  • NavitationController を使っていないので戻るボタンなどがない
  • ボタンを押したときのアクションがデフォルトだと何もない

あたりかなと思います
上 2 つは問題ない可能性が高いですが下の何もアクションがないのは UX 的にまずい気がします
SKAction を駆使すればうまくできるとは思います

参考サイト

0 件のコメント:

コメントを投稿