読者です 読者をやめる 読者になる 読者になる

SpriteKitの物理演算まとめ

iOS SpriteKit ゲームプログラミング

プライベートで開発中のゲームで物理演算理解する必要が出てきたのでまとめ。
超絶ざっくりまとめると

  • SKScene : 重力が働く場そのもの
  • SKNode : 重力によって影響を受けるそれぞれの物体

SKSceneとphysicsWorld

SKSceneは、SpriteKitにおいて物理演算を行う場合に重力が働く場そのものとして振る舞います。
そのため、SKSceneはSKPhysicsWorld型のphysicsWorld propertyを保持しており、 physicsWorldに、gravityspeedなどのpropertyを設定すると、そのSceneにおける重力の効きを定義することができます。
以下は画面下方向へ向かって重力を有効にするための例です。

physicsWorld.gravity = CGVector(dx: 0, dy: -9.8)

SKNodeとphysicsBody

SKNodeは、物理演算において重力によって影響を受ける物体として振る舞います。
そのため、SKPhysicsBody型のphysicsBody propertyを保持し、その初期化時にCGSizeを与えることで、CGSize分の大きさを持つ重力の影響を受ける物体として定義することができます。
コードがあったほうが理解が進むと思いますので、よく使いそうな例をまとめてみました。

背景として表示したい場合

背景として表示したい場合は、SKNodeのインスタンスを作成し、physicsBodyをnilのままにしておけば大丈夫です。

動かないものとして表示したい場合

マリオの土管や、?ブロックですね。
この場合、以下のように書けば大丈夫です。
affectedByGravity = falseを定義することで、重力によって移動しなくなり、 dynamic = falseを定義することで、他のphysicsBodyが当たっても移動しなくなります。

node.physicsBody?.affectedByGravity = false
node.physicsBody?.dynamic = false

最初は動かないが、力を与えると動く場合

マリオの、乗ると落ちる足場などですね。
この場合は、上記の例からdynamic = falseを削除することで実現できます。

node.physicsBody?.affectedByGravity = false

最初は動かないが、力を与えると回転する場合

この場合は、physicsBody?.pinned = trueを定義することで実現できます。

node.physicsBody?.affectedByGravity = false
node.physicsBody?.pinned = true

まとめ

今回は、SpriteKitで物理演算を行う場合、 SKSceneとSKNodeがどのような役割を果たしているか紹介しました。
physicsBodyについてはかなり簡単に説明しましたが、densityやfriction、massなど様々なpropertyを保持していますので、 使う際にそのあたりをもっと深掘りしていこうと思います。

参考