Apple Engine

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

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

Character.swift 過去の記事

 

今回は Character.swift での他の関数とプロパティを見てゆく。

 

node

Character クラスの大本となる characterNode ノードを返す。

GameController.swift 上でこの Character クラスのイニシャライズなどの設定し、 こちらを使いノードを取得して Fox2 のシーンのルートノードに追加する。

var node: SCNNode! {
    return characterNode
}

 

queueResetCharacterPosition()

Max がマップ外に出て Y 座標の値が minAltitude より小さくなった場合、
Max の位置をリセットするフラグを立てる関数。

func queueResetCharacterPosition() {
    shouldResetCharacterPosition = true
}

 

playFootStep()

walkAnimation のアニメーションの際にアニメーションイベントで呼ばれる足音を再生させる関数。

hitTestWithSegment で取得した地面のジオメトリ groundNode が存在していて、isWalking が true の場合に足跡の音をランダムで足音の入った配列を再生する。

ここでの乱数設定では randSnd は 0 〜 19 の範囲になり、stepSoundIndex は min を使用して配列の総数である 9 と randSnd を比較して、少ない方を取るため、9 番目の音が半数以上になる。

func playFootStep() {
    if groundNode != nil && isWalking {
        let randSnd: Int = Int(Float(arc4random()) / Float(RAND_MAX) * Float(Character.stepsCount))
        let stepSoundIndex: Int = min(Character.stepsCount - 1, randSnd)
        characterNode.runAction(SCNAction.playAudio( steps[stepSoundIndex], waitForCompletion: false))
    }
}

 

playJumpSound()

jumpAnimation のアニメーションの際にアニメーションイベントで呼ばれるジャンプ音を再生させる関数。

func playJumpSound() {
    characterNode!.runAction(SCNAction.playAudio(jumpSound, waitForCompletion: false))
}

 

playAttackSound()

spinAnimation のアニメーションの際にアニメーションイベントで呼ばれる攻撃音を再生させる関数。

func playAttackSound() {
    characterNode!.runAction(SCNAction.playAudio(attackSound, waitForCompletion: false))
}

 

isBurning

Max 溶岩に入り燃えているかを表すフラグ。 値をセットした際、過去の値と同じならばスルーし、walkSpeed の値の入れ替えを行う。

溶岩に入っている場合 isBurning が true になり、
true の場合以下の順番で処理がされる。

  • catchFireSound の再生
  • ouchSound の再生
  • Max の点滅(false になるまで繰り返す)
  • 白煙を出す whiteSmokeEmitter のパーティクルを birthRate = 0 で再生停止
  • fireEmitter の birthRate に本来の値 fireEmitterBirthRate を入れパーティクルを再生開始
  • smokeEmitter の birthRate に本来の値 smokeEmitterBirthRate を入れパーティクルを再生開始

 

false の場合以下の順番で処理がされる。

  • Max の全ての音の再生を停止。
  • Max の全てのアクション再生を停止。
  • Max の透明度を戻す
  • aahSound の SE 再生
  • SCNTransaction で白煙の whiteSmokeEmitter の birthRate に本来の値 whiteSmokeEmitterBirthRate を入れパーティクルを再生開始
  • さらに fireEmitter.birthRate、smokeEmitter.birthRate に 0 を入れ再生停止。
  • もう一つの SCNTransaction で5秒後に whiteSmokeEmitter の birthRate に 0 を入れて再生を止める

 

var isBurning: Bool = false {
    didSet {
        if isBurning == oldValue {
            return
        }

        let oldSpeed = walkSpeed
        walkSpeed = oldSpeed
        
        if isBurning {
            model.runAction(SCNAction.sequence([
                SCNAction.playAudio(catchFireSound, waitForCompletion: false),
                SCNAction.playAudio(ouchSound, waitForCompletion: false),
                SCNAction.repeatForever(SCNAction.sequence([
                    SCNAction.fadeOpacity(to: 0.01, duration: 0.1),
                    SCNAction.fadeOpacity(to: 1.0, duration: 0.1)
                    ]))
                ]))
            whiteSmokeEmitter.birthRate = 0
            fireEmitter.birthRate = fireEmitterBirthRate
            smokeEmitter.birthRate = smokeEmitterBirthRate
        } else {
            model.removeAllAudioPlayers()
            model.removeAllActions()
            model.opacity = 1.0
            model.runAction(SCNAction.playAudio(aahSound, waitForCompletion: false))
            
            SCNTransaction.begin()
            SCNTransaction.animationDuration = 0.0
            whiteSmokeEmitter.birthRate = whiteSmokeEmitterBirthRate
            fireEmitter.birthRate = 0
            smokeEmitter.birthRate = 0
            SCNTransaction.commit()
            
            SCNTransaction.begin()
            SCNTransaction.animationDuration = 5.0
            whiteSmokeEmitter.birthRate = 0
            SCNTransaction.commit()
        }
    }
}

 

directionAngle

ユーザー操作から Max の向きを変え Y 軸に directionAngle を渡し 0.1 えアニメーションさせる。

usesShortestUnitArc が true になっているため、 現在の角度から最も近い角度へ回転する。
(例えば、359度に回転させたい場合は反時計回りで359度ではなく、時計回りに-1度回転する)

private var directionAngle: CGFloat = 0.0 {
    didSet {
        characterOrientation.runAction(
            SCNAction.rotateTo(x: 0.0, y: directionAngle, z: 0.0, duration: 0.1, usesShortestUnitArc:true))
    }
}

 

次回は Character クラスの update 関数を見てゆく。