Apple Engine

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

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

Character.swift を見てゆく。

この Swift ファイルはプレイヤーキャラクターである Max の設定とグローバルの関数で構成されている。

f:id:x67x6fx74x6f:20180423180047p:plain

 

キャラクター設定は NSObjct となっており、
GameController.swift の GameController のイニシャライズ時に setupCharacter() が呼ばれ、その中でこのキャラクター設定が呼ばれる。

 

流れ

Character クラス の初期化時に Max の設定、パーティクル、サウンド(SE)、アニメーション情報を読み込んでいる。

それを元に update 関数で移動、ジャンプ、攻撃、アニメーション、SE 再生、障害物の判定が設定されており、 Character クラスの呼び先である GameController クラスの 描画時に呼ばれる SceneRenderer で毎フレームこちらの update 関数が呼ばれている。

 

コード内容

import

Foundation、SceneKit、simd が呼ばれている。

import Foundation
import SceneKit
import simd

 

グローバル関数

地面とキャラクターの接点を求める。
地面である平面の地点、法線、キャラ接地面の法線と接地点と重力を加味した値を元に、 平面の法線とキャラの接地点、平面の法線とキャラの接地面の法線を内積し、割って平面の地点から引く。

この Swift ファイルで設定されている Character クラスの最後の方でこちらを使ってキャラの移動場所を求めている。

func planeIntersect(planeNormal: float3, planeDist: Float, rayOrigin: float3, rayDirection: float3) -> Float {
    return (planeDist - simd_dot(planeNormal, rayOrigin)) / simd_dot(planeNormal, rayDirection)
}

 

Character クラス

NSObject で設定されており、GameController でこちらをイニシャライズされる時、SCNScene を受け取る。

class Character: NSObject {
    ...
}

 

以下、Character クラスの中身

 

定数 / 変数

static private let speedFactor: CGFloat = 2.0
static private let stepsCount = 10
変数名 説明
speedFactor Max の歩くスピードの初期値
stepsCount 後で設定している steps の配列の上限。Step_rock_00 から 09 の mp3 ファイルを SCNAudioSource として設定する。

 

static private let initialPosition = float3(0.1, -0.2, 0)

シーン上に Max が登場する初期位置、またはリセットされた時元に戻すために使う値。
ちなみに地面よりある程度下に行った場合にリセットされるが、基本的にはステージのコリジョンが行く手を阻むため Max が有効範囲外に行く事はなくリセットはされない。

 

static private let gravity = Float(0.004)
static private let jumpImpulse = Float(0.1)
static private let minAltitude = Float(-10)
static private let enableFootStepSound = true
static private let collisionMargin = Float(0.04)
static private let modelOffset = float3(0, -collisionMargin, 0)
static private let collisionMeshBitMask = 8
変数名 説明
gravity 重力の値。Max の downwardAcceleration で高度を設定しおり、この値で引く
jumpImpulse ジャンプ時の弾み具合。downwardAcceleration にこの値を足す
minAltitude 高度の最小値。これより下に行くとキャラクターの位置がリセットされる
enableFootStepSound 歩行音を鳴らすフラグ
collisionMargin コリジョンとキャラとの Y 軸のマージンの設定値
modelOffset キャラと地面のオフセット値を SCNVector3 で設定。 Y 軸にマイナスした collisionMargin を設定している
collisionMeshBitMask コリジョン用のメッシュで当たり判定を行うためのビットマスク

 

enum GroundType: Int {
    case grass
    case rock
    case water
    case inTheAir
    case count
}

Max の現在の状態を調べるための列挙。

 

キャラクター (Max)
private var characterNode: SCNNode!
private var characterOrientation: SCNNode!
private var model: SCNNode!

Max の設定はシーン上では characterNode > characterOrientation > model というノードの構成となっている。

 

変数名 説明
characterNode シーンの addChild されている。移動や効果音再生のアクションなどを設定するトップレベルのノード
characterOrientation characterNode の子となるノードで回転を設定している
model characterOrientation の子となるノードで Max の scn ファイルのジオメトリがあるノードをこちらに設定している。また、ボーンを使用したアニメーションのアクションもこのノードで行なっている

 

物理アニメーション設定
private var characterCollisionShape: SCNPhysicsShape?
private var collisionShapeOffsetFromModel = float3.zero
private var downwardAcceleration: Float = 0
変数名 説明
characterCollisionShape キャラクターのコリジョンを設定する
collisionShapeOffsetFromModel キャラクターのコリジョンのオフセット値を設定する
downwardAcceleration 物理シミュレーションじの高度設定

 

ジャンプ動作設定
private var controllerJump: Bool = false
private var jumpState: Int = 0
private var groundNode: SCNNode?
private var groundNodeLastPosition = float3.zero
var baseAltitude: Float = 0
private var targetAltitude: Float = 0
変数名 説明
controllerJump ジャンプ操作時のフラグ
jumpState ジャンプ時の状態
groundNode 地面のからノード
groundNodeLastPosition groundNode の最終位置を設定する
baseAltitude 基準となる Max の高度。GameController でも変更される
targetAltitude 目標となる Max の高度

 

private var lastStepFrame: Int = 0
private var frameCounter: Int = 0

フレーム毎に frameCounter が1増え、lastStepFrame など比較した際音を鳴らすためのもの。

 

private var previousUpdateTime: TimeInterval = 0
private var controllerDirection = float2.zero

previousUpdateTime は現在より前の更新時間を表す。
controllerDirection は使用箇所不明。

 

状態
private var attackCount: Int = 0
private var lastHitTime: TimeInterval = 0

private var shouldResetCharacterPosition = false
変数名 説明
attackCount 攻撃判別用。0でなければ攻撃している
lastHitTime 最後に敵に当たった時の時間
shouldResetCharacterPosition リセットされる際のフラグ。true になった際 Max の位置がリセットされる

 

パーティクル
private var jumpDustParticle: SCNParticleSystem!
private var fireEmitter: SCNParticleSystem!
private var smokeEmitter: SCNParticleSystem!
private var whiteSmokeEmitter: SCNParticleSystem!
private var spinParticle: SCNParticleSystem!
private var spinCircleParticle: SCNParticleSystem!

private var spinParticleAttach: SCNNode!

private var fireEmitterBirthRate: CGFloat = 0.0
private var smokeEmitterBirthRate: CGFloat = 0.0
private var whiteSmokeEmitterBirthRate: CGFloat = 0.0
変数名 説明
jumpDustParticle ジャンプの際出る砂煙のパーティクル
fireEmitter 溶岩に入った際に尻尾から出る炎のパーティクル
smokeEmitter 溶岩に入った際に尻尾から出る黒煙のパーティクル
whiteSmokeEmitter 尻尾の炎が鎮火した際に出る白煙のパーティクル
spinParticle 攻撃の際のパーティクル。使用不明
spinCircleParticle 攻撃の際の衝撃波のパーティクル
spinParticleAttach max.scn の Max のノード particles_spin_circle を設定する
fireEmitterBirthRate fireEmitter の再生レートの設定
smokeEmitterBirthRate smokeEmitter の再生レートの設定
whiteSmokeEmitterBirthRate whiteSmokeEmitter の再生レートの設定

 

SE
private var aahSound: SCNAudioSource!
private var ouchSound: SCNAudioSource!
private var hitSound: SCNAudioSource!
private var hitEnemySound: SCNAudioSource!
private var explodeEnemySound: SCNAudioSource!
private var catchFireSound: SCNAudioSource!
private var jumpSound: SCNAudioSource!
private var attackSound: SCNAudioSource!
private var steps = [SCNAudioSource](repeating: SCNAudioSource(), count: Character.stepsCount )
変数名 説明
aahSound 溶岩に入り炎が鎮火した際の Max の声
ouchSound 溶岩に入った際のの Max の声
hitSound 敵に当たった時の音
hitEnemySound 敵に攻撃を当てた時の音
explodeEnemySound 敵がやられる時爆発する音
catchFireSound 溶岩に入った際の炎の音
jumpSound Max がジャンプした時の音
attackSound Max が攻撃した時の音
steps Max 歩行時の足音を格納する配列

   

private(set) var offsetedMark: SCNNode?

使用用途不明

 

アクション

GameController から渡されるパラメーター。

var isJump: Bool = false
var direction = float2()
var physicsWorld: SCNPhysicsWorld?
変数名 説明
isJump ジャンプ状態の判定用変数
direction Max の方向をを決める
physicsWorld シーンの physicsWorld が渡される

 

このプロジェクトの中で1番定数と変数が多いため結構な量となっている。

 

次回は Character クラスで実装されている関数について見てゆく。