【Swift】SpriteKitの使い方。物理ボディをクネクネさせながら進ませる。(Swift 2.2、XCode 7.3)
Turbulence Fieldとは
本記事では、SKFieldNodeの「Turbulence Field(以下、乱流ノード)」について説明する。
乱流ノードとは、運動している物理ボディに不規則な加速度を発生させるノードである。この力を受けた物理ボディは蛇行しながら進むようになる。
乱流ノードを使ってみる
実際に乱流ノードをシーンに配置して物理ボディを蛇行させてみよう。以降の手順を行う前のXcodeプロジェクトをGitHubに置いたので、試してみる方はご利用下さい。⇒「テスト用プロジェクト」
事前準備では、ボールと四角をシーンに配置しておいた。
下図赤枠のSKSファイルを選択してシーンエディタを開く。黄緑枠のオブジェクトライブラリボタンを押して部品一覧を表示し、ドラッグ&ドロップで「Turbulence Field」をシーンに配置する(紫矢印)。
黄枠のアトリビュートインスペクタボタンを押して設定画面を表示し、Nameに「turbulence」、Parentに「center_point」、Category Maskに「1」を入力する。Enabledのチェックは付けたままにする。
黒いボールの画像を選択、下図赤枠のアトリビュートインスペクタボタンを押して設定画面を表示し、Field Maskに「1」を入力する。
乱流ノードのCategory Maskと、物理ボディのField Maskのビットマスクを同じにしたので、ボールは乱流ノードの力を受けるようになる。
⇒「ビットマスクとは」
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 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
// // TestScene.swift // import Foundation import SpriteKit class TestScene:SKScene { var startDate:NSDate! //現在シーン設定時の呼び出しメソッド override func didMoveToView(view: SKView) { //シーンを画面サイズに合わせる。 self.scaleMode = .AspectFit //画面端に物理ボディを設定する。 self.physicsBody = SKPhysicsBody(edgeLoopFromRect: self.frame) } //画面タッチ開始時の呼び出しメソッド override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) { //タップ開始日時を取得する。 startDate = NSDate() } //画面タッチ終了時の呼び出しメソッド override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) { //タップ開始から終了までの時間を求める。 let stopDate = NSDate() let zikansa = stopDate.timeIntervalSinceDate(startDate!) //ボールノードを取得する。 let bowlNode = self.childNodeWithName("bowl_black") as? SKSpriteNode //タップした時間の長さに応じた速度で垂直上方向にボールノードを発射する。 bowlNode?.physicsBody?.velocity = CGVector(dx:0, dy:Int(zikansa * 100)) } } |
以下は実際のプレイ動画。垂直上方向に向かってまっすぐ発射したボールが、乱流ノードの影響で蛇行するようになった。
ソースコードで実装する
シーンエディタではなく、ソースコードで乱流ノードを実装する場合は以下のコードのようにする。試してみる場合は、先ほどシーンエディタで追加した乱流ノードを削除してから行うこと。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
//現在シーン設定時の呼び出しメソッド override func didMoveToView(view: SKView) { ‥省略‥ //乱流ノードを作成する。 let turbulenceNode = SKFieldNode.turbulenceFieldWithSmoothness(0.5, animationSpeed: 0.0) //乱流ノードの名前を設定する。 turbulenceNode.name = "turbulence" //乱流ノードのカテゴリマスクを設定する。 turbulenceNode.categoryBitMask = 0b0001 //中心ノードを取得する。 let centerNode = self.childNodeWithName("center_point") as? SKSpriteNode //中心ノードの子に乱流ノードを追加する。 centerNode?.addChild(turbulenceNode) } |
設定項目
乱流ノードのアトリビュートインスペクタの設定項目は、概ね「Liner Gravity Field(以下、線形重力ノード)」と同じなので、そちらを参照されたし。
線形重力ノードの説明と異なる項目を説明する。
Strength
物理ボディが運動しているときに乱流ノードから受ける加速の大きさを指定する。プラス値、マイナス値どちらでも力が発生する。加速度と方向を知る方法は明確になっていないが、設定値の絶対値が大きいほど乱流ノードの力が大きくなる。
以下の動画はstrengthを0に設定した場合のプレイ動画。乱流ノードの力が働かずボールはまっすく進んだ。なお、以降の検証はボールの速度はすべて同じにして実施している。
以下の動画はstrengthを「-1」と「1」に設定した場合のプレイ動画。
以下の動画はstrengthを「-3」と「3」に設定した場合のプレイ動画。乱流が強すぎて前に進めなくなった。
以下の動画はstrengthが「1」のプレイ動画を2つ並べたもの。乱流ノードの力は物理ボディの速さに比例するので、速さとstrengthが同じ場合、物理ボディは同じ動きをする。
Fall off
線形重力ノードと同じで、Falloffにプラス値を設定した場合は、乱流ノードとボールノードとの距離が遠くなるほど加速が弱くなる。
falloffを変更した場合ボールはどんな動きをするのかを確かめておこう。
以下の動画は、strengthは両方とも「1」でfalloffを「0」と「2」で比較したもの。乱流ノードは画面上端に配置している。falloffを「2」に設定したときはノードの直前でクネッと曲がった。
Anim. Speed
Animation Speed(以下、アニメーションスピード)の略。項目名からイメージすると、設定値を上げるとフレームレートのようなものが上がってアニメーションが滑らかになる気がする。しかし、設定値を上げてもアニメーションが滑らかになった様子は無い。
以下はStrengthは両方とも「1」でAnim. Speedの「0」と「0.5」を比較したもの。ちなみにAnim. Speedのデフォルト値は「0」。
描画が滑らかになった様子は無い。そして、Anim Speedを「0.5」にした方は、実行する度に軌跡が変わるようになった。
公式リファレンスのアニメーションスピードの説明には以下のように記載されている。「ノイズと乱流のノードを切り替える割合」のようなことが記載されている。
つまりアニメーションスピードは、描画を滑らかにする設定値では無く、ノイズや乱流の発生割合を変えて動きを不規則にするための設定項目となる。⇒公式リファレンス「SKFieldNode」
The rate at which a noise or turbulence field node changes.
では乱流ノード以外のSKFieldNodeのアニメーションスピードの値を変更するとどうなるのか。やってみた。
以下は線形重力ノードで物理ボディを落下させたプレイ動画、アニメーションスピードを左は「0」、右は「0.5」に設定し、他の設定値はすべて同じで実行した結果、、
何も変わらなかった。。(・_・)
smoothness
smoothnessは、アトリビュートインスペクタの設定項目には無く、ソースコードで乱流ノードを作成するときのメソッドに与える引数である。
公式リファレンスの説明には以下のように記載されている。力を生成するときに使われて、1.0は均一な滑らかさを表しているらしい。デフォルトは0.5に設定されている。
⇒公式リファレンス「SKFieldNode」
The smoothness of the noise used to generate the forces. This parameter should be a value between 0.0 and 1.0, where 1.0 represents a uniform smoothness.
以下の動画は、smoothnessの「0.5」と「1.0」を比較したもの。数値が大きいほど、くねり方が緩やかになった。