【Swift】SpriteKitの使い方。シーンエディタでノードの移動アクションを設定する。(Swift 2.2、XCode 7.3)
シーンエディタでノードを移動させる
本記事ではSpriteKit Sceneファイルの編集画面(以下、シーンエディタ)で設定できるMove ActionとMoveTo Actionについて説明する。
Move Actionとは、シーンに配置したノードを別の座標に移動するアクションである。ソースコードからノードを移動する方法は前回記事までで何度も使ってきた。今回はそれをシーンエディタで実装する。
SpriteKit Sceneファイル(以下、SKSファイル)の作り方については次の記事を参照されたし。⇒「SpriteKit Sceneファイルの使い方」
以降の手順を行う前のXcodeプロジェクトをGitHubに置いたので、試してみる方はご利用下さい。⇒「テスト用プロジェクト」
事前準備では、背景と鳥のノードをSKSファイルのシーンに追加しておいた。
Move Action
下図赤枠のSKSファイルを選択してシーンエディタを開く。Animate横のボタン(黄緑枠)を押してタイムラインを表示する。紫枠のオブジェクトライブラリボタンを押して部品一覧を表示し、ドラッグ&ドロップで「Move Action」を鳥ノードのタイムラインまで運ぶ(水色矢印)。
黄枠のアトリビュートインスペクタボタンを押して設定画面を表示し、Start Timeに「3」、Durationに「2」、Timing Functionに「Linear」、OffsetにX「-200」、Y「-200」を入力する。
以下は実際のプレイ動画。鳥が左下に向かって移動した。
アトリビュートインスペクタの設定項目の内容を説明する。
Start Time
シーンが切り替わったタイミングから何秒後にアクションを実行するかを指定する。
Duration
アクションの所要時間を指定する。
Timing Function
移動時の速度を以下のの4つから選択する。項目名は「Timing Mode」の間違いと思われる。
設定名 | 説明 |
---|---|
Linear | 一定速度で移動する。 |
Ease In | 出発から加速する。 |
Ease Out | 減速しながら到着する。 |
Ease In, Ease Out | 出発時から加速し、減速しながら到着する。 |
以下の動画は、Timing Functionが異なる4つの鳥を画面端に向かって同時にスタートさせたもの。
Offset
現在位置からのノードの移動距離をX方向、Y方向で指定する。単位はポイント。
Offsetとは相対位置のことで、デフォルトではシーンの左下隅が座標を表すときの基準(0, 0)になる。なので、ノードを右または上に進める場合はプラス、左または下に進める場合はマイナスに設定する。
ちなみに、上記と同じ動きをソースコードから実装する場合は、TestScene.swiftを以下のコードに変更する。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
// // TestScene.swift // import Foundation import SpriteKit class TestScene:SKScene { //現在シーン設定時の呼び出しメソッド override func didMoveToView(view: SKView) { //SKSファイルに配置した鳥ノードを取得する。 let bird = self.childNodeWithName("bird") as? SKSpriteNode //3秒待機のアクションを作成する。 let action1 = SKAction.waitForDuration(3.0) //移動のアクションを作成する。 let action2 = SKAction.moveBy(CGVector(dx:-200, dy:-200), duration: 2.0) //一定速度で移動する。 action2.timingMode = SKActionTimingMode.Linear //アクションをまとめる。 let actionAll = SKAction.sequence([action1,action2]) //アクションを実行する。 bird?.runAction(actionAll) } } |
MoveTo Action
Move ActionとMoveTo Actionの違いは、Move Actionは現在位置からの移動距離(相対位置)を指定するのに対し、MoveTo Actionは移動する座標(絶対位置)を指定する点である。
下図はアトリビュートインスペクタの設定項目。
Position
移動先の座標を指定する。デフォルトではシーンの左下隅を基準(0, 0)とした座標を指定する。
その他の設定項目はMove Actionと同じである。同じ動きをソースコードから実装する場合は、TestScene.swiftを以下のコードに変更する。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
// // TestScene.swift // import Foundation import SpriteKit class TestScene:SKScene { //現在シーン設定時の呼び出しメソッド override func didMoveToView(view: SKView) { //SKSファイルに配置した鳥ノードを取得する。 let bird = self.childNodeWithName("bird") as? SKSpriteNode //3秒待機のアクションを作成する。 let action1 = SKAction.waitForDuration(3.0) //移動のアクションを作成する。 let action2 = SKAction.moveTo(CGPoint(x:200, y:100), duration: 2.0) //加速しながら移動する。 action1.timingMode = SKActionTimingMode.EaseIn //アクションをまとめる。 let actionAll = SKAction.sequence([action1,action2]) //アクションを実行する。 bird?.runAction(actionAll) } } |
アクションは下図のように横に並べて順番に実行したり、縦に並べて並列で実行したりできる。たくさんのアクションを組み合わせて、複雑なシーン表現するときはこちらのほうが把握しやすい。
筆者のパソコンでシーンエディタでSKSファイルを編集中にカーネルパニックが発生して、パソコンが勝手に再起動する事象が頻発した(Swift 2.2、XCode 7.3、OS X EI Capitan 10.11.6)。
何やらシーンエディタを開いている状況ではメモリリークが発生するバグがあるようだ。そこで、SKSファイルの編集が終わったら、シーンエディタを開きっぱなしにせずに、ViewController.swiftなどの別のファイルを選択してシーンエディタを閉じるようにしたところ、今のところカーネルパニックは発生していない。⇒参考:stackoverflow「Why Is iOS App Causing Memory Leak in Xcode When Idle?」
もし同じような事象で困っている人がいたら、シーンエディタを開きっぱなしにしないようにして見て下さい。
エラーレポート
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
*** Panic Report *** panic(cpu 0 caller 0xffffff801491f634): "zalloc: zone map exhausted while allocating from zone kalloc.8192, likely due to memory leak in zone kalloc.8192 (2308014080 total bytes, 281737 elements allocated)"@/Library/Caches/com.apple.xbs/Sources/xnu/xnu-3248.60.10/osfmk/kern/zalloc.c:2628 Backtrace (CPU 0), Frame : Return Address 0xffffff80209f3c50 : 0xffffff80148dab52 0xffffff80209f3cd0 : 0xffffff801491f634 0xffffff80209f3e00 : 0xffffff80148c1e37 0xffffff80209f3e30 : 0xffffff80148df25e 0xffffff80209f3e60 : 0xffffff80148c28f8 0xffffff80209f3ea0 : 0xffffff80148d26a5 0xffffff80209f3f10 : 0xffffff80149b8eca 0xffffff80209f3fb0 : 0xffffff80149ecd86 BSD process name corresponding to current thread: WindowServer ‥以下省略‥ |