Apple Engine

Apple, iPhone, iOS, その周辺のことについて

WWDC 2017 の SceneKit サンプル Fox 2 を調べる その26

GameController クラスのセットアップ関数を見てゆく。 今回は敵キャラとパーティクルの設定

 

setupEnemies()

敵の設定。

こちらは以前に紹介しているので割愛。

appleengine.hatenablog.com

 

loadParticleSystems(atPath path: String)

パーティクルセットアップの際に .scn(シーンファイル) や .scnp(パーティクルシステムファイル) から読み込みを容易にするための関数。ファイルパスを指定し呼び出すとパーティクルシステムが入った配列を返す。

引数 path でファイルパスを文字列でとって、ファイル名とディレクトリを使用し、拡張子がパーティクルシステムファイルの場合はそのまま1つのパーティクルが入った配列として返し、シーンファイルの場合はしシーンを全て調べ、見つかったパーティクルを全て配列に入れ返す。

func loadParticleSystems(atPath path: String) -> [SCNParticleSystem] {
    let url = URL(fileURLWithPath: path)
    let directory = url.deletingLastPathComponent()

    let fileName = url.lastPathComponent
    let ext: String = url.pathExtension

    if ext == "scnp" {
        return [SCNParticleSystem(named: fileName, inDirectory: directory.relativePath)!]
    } else {
        var particles = [SCNParticleSystem]()
        let scene = SCNScene(named: fileName, inDirectory: directory.relativePath, options: nil)
        scene!.rootNode.enumerateHierarchy({(_ node: SCNNode, _ _: UnsafeMutablePointer<ObjCBool>) -> Void in
            if node.particleSystems != nil {
                particles += node.particleSystems!
            }
        })
        return particles
    }
}

 

setupParticleSystem()

パーティクルのセットアップ関数。

particleSystems に ParticleKind の enum を添字として、上の loadParticleSystems 関数からパーティクルを格納する。

func setupParticleSystem() {
    particleSystems[ParticleKind.collect.rawValue] = loadParticleSystems(atPath: "Art.scnassets/particles/collect.scnp")
    particleSystems[ParticleKind.collectBig.rawValue] = loadParticleSystems(atPath: "Art.scnassets/particles/key_apparition.scn")
    particleSystems[ParticleKind.enemyExplosion.rawValue] = loadParticleSystems(atPath: "Art.scnassets/particles/enemy_explosion.scn")
    particleSystems[ParticleKind.keyApparition.rawValue] = loadParticleSystems(atPath: "Art.scnassets/particles/key_apparition.scn")
    particleSystems[ParticleKind.unlockDoor.rawValue] = loadParticleSystems(atPath: "Art.scnassets/particles/unlock_door.scn")
}

 

func setupPlatforms()

閉じ込められている仲間の小屋の前の溶岩にある動く橋(mobilePlatform)のアニメーションとパーティクル(particles_platform)の設定。

SCNAction で橋を動かし、パーティクルの orientationDirection を Y 軸 1 の方向に向かせるようにしている。

func setupPlatforms() {
    let PLATFORM_MOVE_OFFSET = Float(1.5)
    let PLATFORM_MOVE_SPEED = Float(0.5)

    var alternate: Float = 1
    
    scene!.rootNode.enumerateHierarchy({(_ node: SCNNode, _ _: UnsafeMutablePointer<ObjCBool>) -> Void in
        if node.name == "mobilePlatform" && !node.childNodes.isEmpty {
            node.simdPosition = simd_float3(
                node.simdPosition.x - (alternate * PLATFORM_MOVE_OFFSET / 2.0), node.simdPosition.y, node.simdPosition.z)

            let moveAction = SCNAction.move(by: SCNVector3(alternate * PLATFORM_MOVE_OFFSET, 0, 0),
                                            duration: TimeInterval(1 / PLATFORM_MOVE_SPEED))
            moveAction.timingMode = .easeInEaseOut
            node.runAction(SCNAction.repeatForever(SCNAction.sequence([moveAction, moveAction.reversed()])))

            alternate = -alternate

            node.enumerateChildNodes({ (_ child: SCNNode, _ _: UnsafeMutablePointer<ObjCBool>) in
                if child.name == "particles_platform" {
                    child.particleSystems?[0].orientationDirection = SCNVector3(0, 1, 0)
                }
            })
        }
    })
}

 

mobilePlatform

particles_platform

 

次回は GameController クラスのオーディオ設定を見てゆく。