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

Swiftで遊ぼう! on Hatena

あしたさぬきblogでやってた初心者オヤジのiOSプログラミング奮闘記がHatenaに来ました

Swiftで遊ぼう! - 757 - Sprite Kit ノードを作ればボディー

質問

今日の記事内で疑問を呈していますが、SKNodeのメソッド「addChild()」はどのオブジェクトから発動しているのでしょうか?

        • -

少し複雑なSKSpriteKitのチュートリアルに取り組んでいます。

www.raywenderlich.com

GameSceneにノードを設定するメソッドを書いています。

func newProjectile () {
    let beaker = SKSpriteNode(imageNamed: "beaker")
    beaker.name = "beaker"
    beaker.zPosition = 5
    beaker.position = CGPoint(x: 120, y: 625)

ここまででSKSpriteNodeオブジェクト(インスタンス)が1つできました。

今日はノードに物理(physics)世界を組み込むのですが、それがSKPhsicsBodyの設定です。

// まずノード(ビーカー)の位置に四角(時に丸く)のボディを着せるような感じです。
    let beakerBody = 
    SKPhysicsBody(rectangleOf: CGSize(width: 40, height: 40))

// 重量と密度もプロパティとして持っています。「mass」は重量になります。
// CGFloat型で「kg」を意味します。
    beakerBody.mass = 1.0

// ここから「カテゴリー」の設定です。カテゴリーはノードの「contact」を
// 判定するために状態を設定します。「PhysicsType.beaker」は、
// グローバル定数としてStruct型で与えられています。
    beakerBody.categoryBitMask = 
        PhysicsType.beaker

GameSceneクラス宣言の前に次のグローバル定数を宣言します。前にも話しましたが、このようなカテゴリーを設定する場合、struct型よりenum型を使った方がいいと思うのですが、ベテランプログラマーの皆さん、どうでしょうか?

struct PhysicsType  {
  static let none            :UInt32  =   0
  static let player          :UInt32  =   1
  static let wall            :UInt32  =   2
  static let beaker          :UInt32  =   4
  static let explosionRadius :UInt32  =   8
  static let cat             :UInt32  =   16
  static let zombieCat       :UInt32  =   32
}

このカテゴリー設定ですが、非常に重要な概念が「bitMask」です。この値は「UInt32」が設定されているんですが、基本的に2進法で表現するので32桁のパターン、要するに32通りの設定ができます。当然、10進法で見れば、2の倍数で表します。2進法を用いるのは、論理計算(ANDやOR)で結果を求める為です。
01 = 0b000001
02 = 0b000010
04 = 0b000100
08 = 0b001000
16 = 0b010000
32 = 0b100000

// ビーカーが衝突判定をしたいのは、ターゲットの猫と壁です。
// ということで「collisionBitMask」は「PhysicsType.cat」
// と「PhysicsType.wall」になります。
    beakerBody.collisionBitMask = 
        PhysicsType.wall | PhysicsType.cat

// 単純ですが、ビーカーの物理世界ができあがったので
// ビーカーに設定してからノードをシーンに追加します。
// 「addChild」はSKSceneのメソッドだと勘違いしていました。
// 実はSKNodeの持ているメソッドです。
// ちょっと疑問点があります。
// どのSKNodeのメソッドが発動しているのでしょうか?
// たぶんGameScene.sksで設定しているSKNodeのどれかだと
// 思います。1番ベースの階層に設定している「bk」
// でしょうか? どなたか教えてくださいm(_ _)m
    beaker.physicsBody = beakerBody
    addChild(beaker)

ここまでの話は、SpriteKitチュートリアルで説明した内容と同じなです。次のコードがノードの融合の話になりますが、明日説明します。

    if let armBody = 
        childNode(
            withName: "player")?.childNode(
                withName: "arm")?.physicsBody {
        pinBeakerToZombieArm = 
            SKPhysicsJointFixed.joint(withBodyA: armBody, 
                                          bodyB: beakerBody, 
                                         anchor: CGPoint.zero)
        physicsWorld.add(pinBeakerToZombieArm!)
        beakerReady = true
    }
}