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 } }
次回に続く。