Swiftで遊ぼう! - 729 - 衝突判定をもう少し考える
Sprite Kitを使って物理空間を実装する時に理解し難い概念が「BitMask」でした。
チュートリアルを読んでも、詳しい説明はされていないからです。プログラミングの基礎が分かっている人はさほど理解に苦しまないでしょう。しかし、私のようにプログラミングの基礎無しで開発をしようとすれば、こういう状況で挫折するかもしれませんね。遠回りですが、やはりちゃんと理解しながら勉強を進める方がいいでしょう。
「BitMask」の使い方は理解できました。PhysicsCategaryをビットを使って理解すると分かり易いということも理解でできました。
ということで、モンスターのPhysicsBodyの設定をしたので、手裏剣「Projectile」のPhysicsBodyの設定コードをみます。
let projectile = SKSpriteNode(imageNamed: "projectile") // ここからphysicsBodyの設定 projectile.physicsBody = SKPhysicsBody(circleOfRadius: projectile.size.width/2) projectile.physicsBody?.isDynamic = true projectile.physicsBody?.categoryBitMask = PhysicsCategory.Projectile projectile.physicsBody?.contactTestBitMask = PhysicsCategory.Monster projectile.physicsBody?.collisionBitMask = PhysicsCategory.None projectile.physicsBody?.usesPreciseCollisionDetection = true
モンスターと違うところは、ボディースーツを丸にしたろころと、「usesPreciseCollisionDetection」を設定したところです。これは動きの速いphysicsBodyの衝突を判定する時に設定しないと素通りしてしまう可能性が出てくるそうです。
そして最後に実装すべきdelegationメソッドをコーディングします。
func didBegin(_ contact: SKPhysicsContact) { var firstBody: SKPhysicsBody var secondBody: SKPhysicsBody if contact.bodyA.categoryBitMask < contact.bodyB.categoryBitMask { firstBody = contact.bodyA secondBody = contact.bodyB } else { firstBody = contact.bodyB secondBody = contact.bodyA } if ((firstBody.categoryBitMask & PhysicsCategory.Monster != 0) && (secondBody.categoryBitMask & PhysicsCategory.Projectile != 0)) { projectileDidCollideWithMonster( projectile: secondBody.node as! SKSpriteNode, monster: firstBody.node as! SKSpriteNode) } }
このコードも定型文のような内容です。衝突が生じた時に渡される2つのphysicsBodyの順番が決まっていないので、categoryBitMaskを使って判断します。そしてその効果判定をするのが「if」文です。「&」がANDオペレータなんで、ビット計算させればいいんです。簡単に理解できるでしょう。
「projectileDidCollideWithMonster」はカスタムメソッドです。衝突していたらノードを消すステップを組みます。
func projectileDidCollideWithMonster(projectile:SKSpriteNode, monster:SKSpriteNode) { print("Hit") projectile.removeFromParent() monster.removeFromParent() }
これでランしたら遊ぶことができました。コードの理解もできたしプログラムは動くし、少しずつですがiOS開発が分かってきています。
今日はこれだけ。