【Swift】SpriteKitの使い方。SKActionを使ってノードを移動、回転、拡大縮小する。(Swift 2.2、XCode 7.3)
SKActionとは
本記事ではSKScene(以下、シーン)に配置したノードをSKActionを用いて状態変化させる方法を説明する。
SKActionとは、移動、回転、拡大縮小などノードの状態を変化させるためにノードに与えるアクションクラスのことである。
以降の手順を行う前のXcodeプロジェクトをGitHubに置いたので、試してみる方はご利用下さい。
⇒「テスト用プロジェクト」
シーンに背景と鳥のノードを配置しておいた。このプロジェクトを変更し、画面タップで鳥ノードの状態が変化するようにする。
以下のコードは変更前のTestScene.swift。
TestSceneが現在シーンになったら、背景画像と鳥のノードをシーンに追加している。
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 34 35 36 37 |
// // TestScene.swift // import Foundation import SpriteKit class TestScene:SKScene { var birdNode:SKSpriteNode! //現在シーン設定時の呼び出しメソッド override func didMoveToView(view: SKView) { //背景画像のノードを作成する。 let backNode = SKSpriteNode(imageNamed: "mountain") //背景画像のサイズをシーンと同じにする。 backNode.size = self.frame.size //背景画像の位置をシーンの中央にする。 backNode.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame)); //鳥のノードを作成する。 birdNode = SKSpriteNode(imageNamed: "bird1") //鳥の位置をシーンの中央にする。 birdNode.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame)); //ノードをシーンに追加する。 self.addChild(backNode) self.addChild(birdNode) } } |
ノードの状態を変化させるのにはSKActionクラスを利用する。
以下の例のように、目的別のSKActionインスタンスを取得し、ノードのrunActionメソッドの引数に与えてやればノードの状態が変化する。
//移動のSKActionを取得する
let action = SKAction.moveTo(CGPoint(x:X座標, y:Y座標), duration:時間)
//アクションを実行する。
birdNode.runAction(action)
以下は、SKActionのメソッド。他にもたくさんのメソッドがあるので興味のある方は公式リファレンスを参照されたし。⇒「SKAction」
メソッド名 | 説明 |
---|---|
moveTo | 指定した座標(X,Y)に移動する。 let action = SKAction.moveTo(CGPoint(x:200, y:200), duration:1.0) |
moveToX | 指定したX座標に移動する。Y座標には変化しない。 let action = SKAction.moveToX(200, duration:1.0) |
moveToY | 指定したY座標に移動する。X座標には変化しない。 let action = SKAction.moveToY(200, duration:1.0) |
moveBy | 現在位置から指定した長さ(ポイント)を移動する。 let action = SKAction.moveBy(CGVector(dx: 90,dy: 90), duration: 1.0) |
moveByX | 現在位置から指定した長さ(ポイント)を移動する。 llet action = SKAction.moveByX(90, y: 90, duration: 1.0) |
followPath | パスに沿って移動する let path = CGPathCreateMutable() CGPathMoveToPoint(path, nil, 0, 0) CGPathAddLineToPoint(path, nil, 100, 100) CGPathAddLineToPoint(path, nil, 100, -100) let action = SKAction.followPath(path, duration: 1.0) |
rotateToAngle | 指定した角度に回転する。 let action = SKAction.rotateToAngle(CGFloat(M_PI_2), duration: 1.0) |
rotateByAngle | 現在角度からさらに指定した角度を回転する。 let action = SKAction.rotateByAngle(CGFloat(M_PI_2), duration: 1.0) |
scaleTo | 指定した倍率まで拡大縮小する(1.0が等倍)。 let action = SKAction.scaleTo(1.5, duration: 1.0) |
scaleBy | 現在の倍率からさらに指定した倍率まで拡大縮小する。 let action = SKAction.scaleBy(1.5, duration: 1.0) |
scaleXBy | 現在の倍率からさらに指定した倍率(X、Yを指定)まで拡大縮小する。 let action = SKAction.scaleXBy(2.0, y: 3.0, duration: 1.0) |
scaleXTo | 指定した倍率まで水平方向に拡大縮小する。 let action = SKAction.scaleXTo(1.5, duration: 1.0) |
scaleYTo | 指定した倍率まで垂直方向に拡大縮小する。 let action = SKAction.scaleYTo(1.5, duration: 1.0) |
resizeToWidth | 指定した幅まで画像を拡大縮小する。 let action = SKAction.resizeToWidth(200, duration: 1.0) |
resizeToHeight | 指定した高さまで画像を拡大縮小する。 let action = SKAction.resizeToHeight(200, duration: 1.0) |
resizeByWidth | 現在のサイズからさらに指定した幅と高さを追加したサイズまで拡大縮小する。 let action = SKAction.resizeToWidth(200, duration: 1.0) |
タップした位置にノードを移動する
TestScene.swiftに以下のメソッドを追加する。
画面をタッチしたらtouchesBeganメソッドが呼び出されるので、SKActionを用いてタッチされた座標までノードを移動している。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
//画面タッチ開始時の呼び出しメソッド override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) { //タッチした座標を取得する。 let location = touches.first!.locationInNode(self) //タッチした位置まで移動するアクションを作成する。 let action = SKAction.moveTo(CGPoint(x:location.x, y:location.y), duration:1.0) //アクションを実行する。 birdNode.runAction(action) } |
以下は実際のプレイ動画
アクションを組み合わて同時に実行する
タップした位置にノードを移動するだけでなく、移動している間に他のアクションも実行したいことがある。そんなときはgroupメソッドを使ってアクションを1つにまとめて実行する。
実際にやってみよう。先ほど追加したtouchesBeganメソッドを以下のように修正する。
タッチした位置まで移動するアクションと、5回転するアクションと、サイズが1.2倍になるアクションをまとめて実行している。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
//画面タッチ開始時の呼び出しメソッド override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) { //タッチした座標を取得する。 let location = touches.first!.locationInNode(self) //移動、回転、拡大のアクションを作成する。 let action1 = SKAction.moveTo(CGPoint(x:location.x, y:location.y), duration:1.0) let action2 = SKAction.rotateByAngle(CGFloat(M_PI * 5), duration: 1.0) let action3 = SKAction.scaleBy(1.2, duration: 1.0) //アクションをまとめる。 let actionAll = SKAction.group([action1,action2,action3]) //アクションを実行する。 birdNode.runAction(actionAll) } |
以下は実際のプレイ動画
組み合わせたアクションを順番に実行する
順番にアクションを実行する場合は、以下のコードのようにsequenceメソッドでアクションをまとめる。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
//画面タッチ開始時の呼び出しメソッド override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) { //タッチした座標を取得する。 let location = touches.first!.locationInNode(self) //移動、回転、拡大のアクションを作成する。 let action1 = SKAction.moveTo(CGPoint(x:location.x, y:location.y), duration:1.0) let action2 = SKAction.rotateByAngle(CGFloat(M_PI * 5), duration: 1.0) let action3 = SKAction.scaleBy(1.2, duration: 1.0) //アクションをまとめる。 let actionAll = SKAction.sequence([action1,action2,action3]) //アクションを実行する。 birdNode.runAction(actionAll) } |
以下は実際のプレイ動画
ノードをドラッグで移動する
先ほど追加したtouchesBeganメソッドは削除して、以下のメソッドを追加する。
指を画面に触れたまま移動したときにtouchesMovedメソッドが呼び出されるので、タッチされている座標までノードを移動している。このメソッドは指の位置が変わるたびに呼び出される。
指と全く同じ座標にノードを移動すると指でノードが隠れて見えにくいので、指の位置から20ポイント上に移動するようにした。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
//画面タッチ移動時の呼び出しメソッド override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) { //タッチした座標を取得する。 let location = touches.first!.locationInNode(self) //タッチした位置まで移動するアクションを作成する。 let action = SKAction.moveTo(CGPoint(x:location.x, y:location.y + 20), duration:0.1) //アクションを実行する。 birdNode.runAction(action) } |
以下は実際のプレイ動画