【Swift】SpriteKitの使い方。物理ボディを等速度運動させる。(Swift 2.2、XCode 7.3)
Velocity Fieldとは
本記事では、SKFieldNodeの「Velocity Field(以下、等速度ノード)」について説明する。
等速度ノードとは、物理ボディを等速度運動させるノードである。以前説明したLinear Gravity Field(以下、線形重力ノード)は物理ボディを加速させるのに対し、等速度ノードは加速させない点が異なる。
等速度ノードを使ってみる
実際に等速度ノードをシーンに配置して物理ボディを等速度運動させてみよう。以降の手順を行う前のXcodeプロジェクトをGitHubに置いたので、試してみる方はご利用下さい。⇒「テスト用プロジェクト」
下図赤枠のSKSファイルを選択してシーンエディタを開く。黄緑枠のオブジェクトライブラリボタンを押して部品一覧を表示し、ドラッグ&ドロップで「Velocity Field」をシーンに配置する(紫矢印)。
黄枠のアトリビュートインスペクタボタンを押して設定画面を表示し、Nameに「velocity」、DirectionにX「0」、Y「-2」、Category Maskに「1」を設定、Enabledのチェックを外す。
ボールの画像を選択、下図赤枠のアトリビュートインスペクタボタンを押して設定画面を表示し、Field Maskに「1」を入力する。
等速度ノードのCategory Maskと、物理ボディのField Maskのビットマスクを同じにしたので、ボールは等速度ノードの力を受けるようになる。
⇒「ビットマスクとは」
TestScene.swiftのtouchesBeganメソッドを以下のコードに変更する。
1 2 3 4 5 6 7 8 9 10 11 |
//画面タッチ開始時の呼び出しメソッド override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) { //等速度ノードを取得する。 let velocityNode = self.childNodeWithName("velocity") as? SKFieldNode //等速度ノードの効果を有効にする。 velocityNode?.enabled = true } |
以下は実際のプレイ動画。
ソースコードで実装する
シーンエディタではなく、ソースコードで等速度ノードを実装する場合は以下のコードのようにする。試してみる場合は、先ほどシーンエディタで追加した等速度ノードを削除してから行うこと。
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 noiseNode = SKFieldNode.velocityFieldWithVector(vector_float3(0,-2.0,0)) //等速度ノードの名前を設定する。 noiseNode.name = "velocity" //等速度ノードの効果を無効にする。 noiseNode.enabled = false //等速度ノードのカテゴリマスクを設定する。 noiseNode.categoryBitMask = 0b0001 //シーンに等速度ノードを追加する。 self.addChild(noiseNode) } |
線形重力ノードの場合と比較して、本当に等速度運動なのかを確かめよう。
以下の動画は、左側は線形重力ノード、右側は等速度ノードを用いてボールを運動させたもの。vector_float3は両方ともY軸方向「-2.0」に設定した。
加速する左側のほうが早く画面下端に到着しそうな気がするが、実際は右側のほうが早く到着した。線形重力ノードと等速度ノードのdirectionプロパティの作用が異なることになるが、深追いしないでおく。
落下開始から一定時間ごとのボールの位置を横並びにして加速を確認してみよう。1秒を15フレームに分割して観測した。
下図は左側(線形重力ノード)の0.33秒(5フレーム)ごと落下位置。ボールが加速していることが分かる。
下図は右側(等速度ノード)の0.33秒(5フレーム)ごと落下位置。ボールが等速度運動していることが分かる。
設定項目
等速度ノードのアトリビュートインスペクタの設定項目は、概ね「Liner Gravity Field(以下、線形重力ノード)」と同じなので、そちらを参照されたし。
線形重力ノードの説明と異なる項目を説明する。
Strength
この設定値を変更しても物理ボディの運動は何も変わらない。等速度ノードの力はDirectionの設定値で決まる。
Falloff
この設定値を変更しても物理ボディの運動は何も変わらない。
試しにボールを下図のように縦に並べて、falloffに効果があるのか実験してみよう。等速度ノードは画面左下に配置する。
TestScene.swfitのtouchessBeganメソッドを以下のコードに変更する。falloffを「10.0」、vector_float3をX軸方向「2.0」に設定した。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
//画面タッチ開始時の呼び出しメソッド override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) { //等速度ノードを作成する。 let velocityNode = SKFieldNode.velocityFieldWithVector(vector_float3(2.0,0,0)) //減衰を設定する。 velocityNode.falloff = 10.0 //位置を設定する。 velocityNode.position = CGPoint(x: 0, y: 0) //等速度ノードをシーンに配置する。 self.addChild(velocityNode) } |
以下は実際のプレイ動画。すべてのボールが同じ速度で等速度運動した。これにより、等速度ノードのfalloffプロパティも効果が無いことが明らかになった。
Direction
X軸方向とY軸方向の速度の大きさを指定する。Directionは等速度ノード専用のプロパティである。(Swift 2.2、XCode 7.3)
以下の動画は、DirectionにX「3」、Y「-3」を設定した場合のプレイ動画
velocityFieldWithTexture
等速度ノードを作るときのメソッドには、velocityFieldWithVectorメソッドの他にもう一つ、velocityFieldWithTextureメソッドがある。
等速度ノードの効果をテクスチャで指定するメソッドのようだが、動作確認が取れない。
以下のコードのようにするとボールが運動するようになるが、これはテクスチャの代わりにdirectionプロパティが用いられただけのようだ。
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 texture = SKTexture(imageNamed: "bowl_black") //等速度ノードを作成する。 let velocityNode = SKFieldNode.velocityFieldWithTexture(texture) //速度の大きさを設定する。 velocityNode.direction = vector_float3(2.0,0,0) //等速度ノードの位置を設定する。 velocityNode.position = CGPoint(x: 0, y: 0) //等速度ノードをシーンに配置する。 self.addChild(velocityNode) } |
気になるのでテクニカルフォーラムに投稿してみた。何かわかったら追記する。