衝突処理

Sprite Kitは物体の衝突処理を計算して物理シミュレーションをおこなってくれる。少し複雑なので、基本的な事は理解しておいてから利用したほうが良いでしょう。

動体の設定

Sprite Kitにスプライトがどんな形をしているかを知らせるために、physicsBodyにスプライトの形を作成する。あまり複雑にすると処理に時間がかかるので、円形や矩形(四角)で問題なければそれを利用するのが良いでしょう。

矩形の動体の追加

sprite1.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:sprite1.size];

円形の動体の追加

sprite1.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:sprite1.size.width / 2.0];

パスから開いた境界線を作成

sprite1.physicsBody = [SKPhysicsBody bodyWithEdgeChainFromPath:path1];

2点間をつなぐ境界線を作成

sprite1.physicsBody = [SKPhysicsBody bodyWithEdgeFromPoint:CGPointMake(0,0) toPoint:CGPointMake(100,100)];

パスからループした境界線を作成

sprite1.physicsBody = [SKPhysicsBody bodyWithEdgeLoopFromPath:path1];

矩形のループした境界線を作成

sprite1.physicsBody = [SKPhysicsBody bodyWithEdgeLoopFromRect:CGRectMake(0,0,50,50)];

パスからポリゴンの物理体を作成 

sprite1.physicsBody = [SKPhysicsBody bodyWithPolygonFromPath:path1];

衝突時にメソッドが呼ばれるようにする

初期設定
シーンのクラスにSKPhysicsContactへのデリゲートを指定しておく
例:

@interface MyScene : SKScene <SKPhysicsContactDelegate>

シーンのinitWithSizeメソッドで、

self.physicsWorld.contactDelegate = self;

物体にBitMaskを設定(設定しないと衝突判定メソッドが呼ばれない)

self.sprite1.physicsBody.categoryBitMask = 0x1 << 0; // 自分が属するカテゴリー 初期値は0xFFFFFFFF
self.sprite1.physicsBody.collisionBitMask = 0x1 << 1; // ここで設定した物体とだけ衝突する 初期値は0xFFFFFFFF
self.sprite1.physicsBody.contactTestBitMask = 0x1 << 0 | 0x1 << 1; // ここで設定した物体とだけ衝突した時、衝突判定のメソッドが呼ばれる 初期値が0x00000000のため設定しないと後述のdidBeginContactが呼ばれない

衝突判定メソッド

物体の衝突時になんらかの処理を行いときは下記メソッドを使う

- (void)didBeginContact:(SKPhysicsContact *)contact {
    // 記述例、下記例ではbodyAとbodyBのnameが逆の場合があることを考慮していないので注意
    if ([contact.bodyA.node.name isEqualToString:@"sprite1"]
            && [contact.bodyB.node.name isEqualToString:@"sprite2"]) {
        [contact.bodyB.node removeFromParent];
    }
}

重力の設定

self.physicsWorld.gravity = CGVectorMake(0, 0); // 重力を0にしたい時、初期値は(0.0,-9.8)。単位はm/sec

動かさない物体

self.sprite1.physicsBody.dynamic = NO; // 地面や壁など

力をかける

[self.sprite1.physicsBody applyForce:CGVectorMake(x, y)];
// または、[self.sprite1.physicsBody applyImpulse:CGVectorMake(x, y)]; // 衝撃を加える

画面サイズと同サイズのボーダーを作る

self.physicsBody = [SKPhysicsBody bodyWithEdgeLoopFromRect:CGRectMake(0,0,self.size.width,self.size.height)];

初期状態では物体は画面外へと落ちて消えていきます。物体が画面外へ出ないようにするには、画面サイズと同じ境界線を作ってあげます。