【Swift】SpriteKitの使い方。物理運動の抵抗力を発生させて動きをスローにする。(Swift 2.2、XCode 7.3)
Drag Fieldとは
本記事では、SKFieldNodeの「Drag Field(以下、抗力ノード)」について説明する。
抗力ノードとは、物理ボディの動きに対する抵抗力を発生させるノードである。例えば、ボールを水槽の中に落としたとき、空気中を落下するよりもゆっくりと落下していく。これはボールに対する浮力と抵抗力が働くためである。
ちなみにDrag Fieldの「Drag」は「抗力」という意味。ドラッグ&ドロップの「ドラッグ」と勘違いしそうな名前だ。
抗力ノードを使ってみる
実際に抗力ノードをシーンに配置して物理ボディを落下させてみよう。以降の手順を行う前のXcodeプロジェクトをGitHubに置いたので、試してみる方はご利用下さい。⇒「テスト用プロジェクト」
事前準備ではボールをシーンに配置しておいた。
下図赤枠のSKSファイルを選択してシーンエディタを開く。黄緑枠のオブジェクトライブラリボタンを押して部品一覧を表示し、ドラッグ&ドロップで「Drag Field」をシーンに配置する(紫矢印)。
黄枠のアトリビュートインスペクタボタンを押して設定画面を表示し、Nameに「drag」、Parentに「center_point」、Category Maskに「1」を入力する。Enabledのチェックは入れたままにする。
黒ボールの画像を選択、下図赤枠のアトリビュートインスペクタボタンを押して設定画面を表示し、Field Maskに「1」を入力する。
抗力ノードのCategory Maskと、物理ボディのField Maskのビットマスクが同じなので、ボールは抗力ノードの物理的効果を受けるようになる。
⇒「ビットマスクとは」
TestScene.swiftのtouchesBeganメソッドを以下のコードに変更する。画面がタップされたら重力でボールが落下するようにした。
1 2 3 4 5 6 7 8 9 10 |
//画面タッチ時の呼び出しメソッド override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) { //ボールノードを取得する。 let bowlNode = self.childNodeWithName("bowl_black") as? SKSpriteNode //ボールノードに重力加速度を発生させる。 bowlNode?.physicsBody?.affectedByGravity = true } |
以下は実際のプレイ動画。左側は抗力ノードを無効にしたもので、右側は有効にしたもの。右側は抗力ノードの抵抗力により通常よりボールがゆっくり落下した。
落下開始から一定時間ごとのボールの位置を横並びにして加速を確認してみよう。1秒を15フレームに分割して観測した。
下図は左側動画(抗力ノードを無効)の0.13秒(2フレーム)ごと落下位置。ボールが加速していることが分かる。
下図は右側動画(抗力ノードを有効)の0.33秒(5フレーム)ごとの落下位置。移動開始直後以外は加速していないことが分かる。
これにより、水中での落下と同じように、抗力ノードの抵抗によって物理ボディの落下速度がすぐに一定になることが明らかとなった。
ソースコードで実装する
シーンエディタではなく、ソースコードで抗力ノードを実装する場合は以下のコードのようにする。試してみる場合は、先ほどシーンエディタで追加した抗力ノードを削除してから行うこと。
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 dragNode = SKFieldNode.dragField() //抗力ノードの名前を設定する。 dragNode.name = "drag" //抗力ノードのカテゴリマスクを設定する。 dragNode.categoryBitMask = 0b0001 //中心ノードを取得する。 let centerNode = self.childNodeWithName("center_point") as? SKSpriteNode //中心ノードの子に抗力ノードを追加する。 centerNode?.addChild(dragNode) } |
設定項目
抗力ノードのアトリビュートインスペクタの設定項目は、概ね「Liner Gravity Field(以下、線形重力ノード)」と同じなので、そちらを参照されたし。
線形重力ノードの説明と異なる項目を説明する。
Strength
物理ボディの運動に対する抵抗力の強さを設定する。あくまで抵抗力であって、運動せずに止まっている物理ボディを引き寄せたり、遠ざけたりする力は働かない。0は抵抗無し。マイナスにすると訳の分からない動きをする。
なお、SKActionのmoveメソッドなどの移動のアニメーションには抵抗力は発生しない。
以下の動画は、左側がStrength「1」、右側がStrength「10」の動画
Falloff
物理的効果の減衰率を設定する。抗力ノードから距離が離れると抵抗力が弱くなるということ。
抗力ノードから見て物理ボディがどこにいても、抵抗力は物理ボディの進行方向の逆向きに働く。例えば、下図のように抗力ノードを通り過ぎた直後のボールへの抵抗力は離れた位置よりも強いが、下に向かって強い抵抗力が働くわけではなく、進行方向の逆方向に抵抗力が働く。
以下の動画は左側がFalloff「0」、右側がFalloff「0.8」の動画。右側は出だしは速いが抗力ノードに近づくにつれ減速し、抗力ノードを過ぎると加速した。
以下の動画は、Falloffは「0.8」に設定したままで、画面左右端にボールを追加し同時に落下させたもの。左右のボールは抗力ノードから少し離れて落下するため、中央のボールよりも早く地面に着地する。