Apple Engine

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

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

今回は GameController クラスの残りの関数を見てゆく。

 

プレイヤーキャラクター Max の初期位置リセット

Max がマップから落ちた時など、resetPlayerPosition() から Character クラスの queueResetCharacterPosition() を呼ぶ。

func resetPlayerPosition() {
    character!.queueResetCharacterPosition()
}

 

カメラ処理

宝石のアイテム取得、仲間を助けた時の画面処理と Max の停止を行う関数。

startCinematic() は playingCinematic を true にして isPaused で Max の動作を止める。
startCinematic() その反対をする。

func startCinematic() {
    playingCinematic = true
    character!.node!.isPaused = true
}

func stopCinematic() {
    playingCinematic = false
    character!.node!.isPaused = false
}

   

パーティクル処理

particleSystems(with kind: ParticleKind) で ParticleKind no enum から particleSystems 呼び出す処理で、次の addParticles 関数で使用。

addParticle はアイテム取得や仲間を助ける際に表示するパーティクルで、引数の ParticleKind と 座標値を元にシーンに配置している。

func particleSystems(with kind: ParticleKind) -> [SCNParticleSystem] {
    return particleSystems[kind.rawValue]
}

func addParticles(with kind: ParticleKind, withTransform transform: SCNMatrix4) {
    let particles = particleSystems(with: kind)
    for ps: SCNParticleSystem in particles {
        scene!.addParticleSystem(ps, transform: transform)
    }
}

 

トリガー

Max が透明度 0 で見えなくなっている立方体に接触するとトリガーが弾かれカメラ変更が行われ視点が変わるようになっている。   基本的には、実行部分である execTrigger 関数が trigger 関数から呼ばれ動作する。
鍵のアイテム出現後に元の位置へ戻る際、キャラクターが止まっておりトリガーが弾けないので、その時だけ execTrigger 関数を直接叩いている。

 

execTrigger

カメラ視点を買えるものと仲間を助けるトリガーが設定している。

トリガーのノード、アニメーション時間を引数とし、トリガーノード名が trigCam〜 の場合は "trigCam" を消したものをカメラの名前として setActiveCamera からアニメーション時間とともに呼び出す。

トリガーノード名が trigAction〜 で鍵のアイテムが取得されている場合は アクションの名前から "trigAction" 取り除く。
取り除いた文字列が "unlockDoor" なら unlockDoor() を呼び出し、仲間を助ける。

func execTrigger(_ triggerNode: SCNNode, animationDuration duration: CFTimeInterval) {
    if triggerNode.name!.hasPrefix("trigCam_") {
        let cameraName = (triggerNode.name as NSString?)!.substring(from: 8)
        setActiveCamera(cameraName, animationDuration: duration)
    }
    if triggerNode.name!.hasPrefix("trigAction_") {
        if collectedKeys > 0 {
            let actionName = (triggerNode.name as NSString?)!.substring(from: 11)
            if actionName == "unlockDoor" {
                unlockDoor()
            }
        }
    }
}

 

trigger(_ triggerNode: SCNNode)

playingCinematic が true の場合はトリガーの処理は行わない。

保存した最後のトリガーノード保持している lastTrigger と 現在のトリガーノードが異なっていたら lastTrigger に現在のトリガーノードを保存。

execTrigger を実行し、トリガーが引かれたこと判別する firstTriggerDone を true する。

func trigger(_ triggerNode: SCNNode) {
    if playingCinematic {
        return
    }
    if lastTrigger != triggerNode {
        lastTrigger = triggerNode

        execTrigger(triggerNode, animationDuration: firstTriggerDone ? GameController.DefaultCameraTransitionDuration: 0)
        firstTriggerDone = true
    }
}

 

次回に続く。