はじめに
iOSにSceneKitという3Dライブラリがあるのですが、学習がてら、それを利用して簡単なゲームを作ってみました。
ThreeDMaze
https://itunes.apple.com/us/app/threedmaze/id973497184
ソースコード
https://github.com/xylitol45/ThreeDMaze
気付いたことをメモってみます。
SCNNode.flattenClone
同じ内容のSNNode(3Dオブジェクト)をあちこちに配置する場合、flattenClone
を利用して、コピーしたSCNNodeを配置すると最適化されてよいらしいです。
SCNCameraのxFov、yFovは角度指定
カメラの画角(広角とか)の指定はSCNCamera
のxFov
、yFov
を利用します。
ただ、何か理由があるのかもしれませんが、他の回転がほぼラジアン指定なのに対し、ここは角度(0-360)で指定するようになってました。
rotateByAngle:aroundAxis:duration:
SCNAction
を利用して、SCNNodeに対し、回転や移動などのアニメーションを設定することができます。
回転の指定は色々あるのですが、今回カメラの回転を行う為に、結局 rotateByAngle:aroundAxis:duration:
を使いました。
SCNAction.rotateByAngle(CGFloat(M_PI) * -2, aroundAxis: SCNVector3(x: 1, y: 1, z: 1), duration: 10)
他の回転処理を連続で使うとどうもズレてしまう。。。
(四元数とかジンバルロックとかよく分かってないというのもある)
ただし、このAPIを使うと、現在、アプリの申請時に警告が出るようです。
The app references non-public selectors in Payload/ThreeDMaze.app/ThreeDMaze:rotateByAngle:aroundAxis:duration:
でも、ないはずはないので、これはさっくり無視した感じです(リリースはできた)。
カメラの移動とアニメーション
実機での確認はiPhone6がメインでした。
で、当初、迷路内のオブジェクトにもSCNAction
でアニメーション効果をつけていたのですが(迷路内のコインをくるくる回してた)、カメラを回転させると、アプリが落ちまくる。。。
動きの早さはそんなに悪くないんですけどね。
結局、アニメーション効果はあきらめました。
SCNSceneRenderer.overlaySKScene
3D画面へのオーバレイ画面として、SCNSceneRenderer.overlaySKScene
を利用し、SpriteKitのSKScene
を設定することができます。
ただ、SpriteKitの感覚で使ってたら若干挙動が違っていて、
-
SKScene.scaleMode
がうまく動いてない?frame
は実値で指定したほうがよさげ。 - 親となる
SCNView
で再描画されないと、画面更新されないような。結局、CADisplayLink
を利用する形になりました。
// CADisplayLinkを利用して、loop処理を作る
if displayLink == nil {
displayLink = CADisplayLink(target: self, selector: Selector("loop:"))
displayLink?.addToRunLoop(NSRunLoop.currentRunLoop(), forMode: NSRunLoopCommonModes)
}
func loop(link:CADisplayLink) {
if startTime == nil {
startTime = link.timestamp
}
if link.timestamp - lastTime > 0.01 {
lastTime = link.timestamp
// ここでSKLabelNode変更
refreshTimeLabel(Double(lastTime - startTime!))
self.view!.setNeedsDisplay()
}
}
迷路作成
ここを参考にしたのですが、迷路の作り方は色々あるようです。
迷路自動生成アルゴリズム
http://www5d.biglobe.ne.jp/stssk/maze/make.html
今回は立体ということもあり「穴掘り法(道延ばし法)」というのを利用しました。
- まず迷路を全て壁で埋め尽くす。
- 適当な基点を設定する。
- その基点からランダムに2マス穴を掘れる方向を探す。
- 2マス掘って、新たな基点とし、3を繰り返す。
- 穴に当たって掘れなくなったら、今までの基点から適当なものを選び新たな基点とする。
3Dモデル
今回は使ってませんが。
SceanKitですが、3Dモデルとして、COLLADAフォーマット(.dae)を扱うことができます。
ただ、これについてはよく指摘されているようですが、プロジェクトに追加すると、独自の形式に変換されているようです。
UIWebView + three.js でこのリソースを扱おうとしても、正しく読み込めません。
.datとか拡張子を変えて追加すると、正しく読み込めるようです。
(でも、おそらくSceneKitからは使えないような)
Unity
世の中的には Unityのほうがメジャーなのですが、SceneKitは無料なので、カジュアルに何か作るにはいいかな、と思います。
Unity無印のiOS出力アドオンっていつの間にか無料になってた。。。