Papervision 3Dでシンプル立体迷路を作る勉強
カーソルキーで動かしてください。
あんまり複雑にならないように、立体迷路を作ります。
- XMLを読んで、地図を解析する。
- XML通りに壁を作っていく(Cubeクラス)
- Cubeオブジェクトに貼るマテリアル(テクスチャ)には取り急ぎ1枚の画像で間に合わせる。
- 移動キャラにはこちらもまずは紙飛行機オブジェクト(PaperPlane)を使う
- 紙飛行機はカーソルキーで左右に向き(角度)を変える
- 紙飛行機の移動はカーソルキー上下で行う
- カメラが紙飛行機の後を追従していく
- カメラは角度も紙飛行機の方角を狙い続ける
- 紙飛行機が壁に衝突したらそれ以上進まないようにする
まず、XMLの読み方としては、多くの方がEventDispatcherクラスを継承したXMLを読み込み完了したイベントを知らせるクラスを経由した後に解析する事が多いですが、ひとまず簡単に省略してしまいました。
外部に配置されているXMLファイルはこんな感じです。
0が通路で1が壁。それだけで試してみます。
一度Scene3Dクラスでシーンを作成してカメラはCamera3Dクラスを使います。
Viewport3Dではレンダリングする範囲などを決定させるために、第1,2引数にはステージサイズを入れておいて画面いっぱいを表示範囲にしてしまいましょう。この3つのオブジェクトはレンダリングする時に必要な要素になります。
さて、それらをレンダリングするエンジンとなるオブジェクトを作成するためにBasicRenderEngineクラスを使う、先ほどの3つのオブジェクトはこれによって関連付けられます。
DisplayObject3DクラスのインスタンスrootNodeを一つ作ったら、その中に『表示3Dオブジェクト』を入れてあげると階層3D空間を作る事が出来ます。
インスタンスrootNodeの中に紙飛行機PaperPlaneクラスのインスタンスをaddChild、さらにXMLを読み終わったら解析をして、配列にCubeオブジェクトを作成しながら、こちらもインスタンスrootNodeにaddChildさせるだけです。
Cubeオブジェクトの場合テクスチャを貼る場合は他クラスとちょっと違ってMaterialsListで各面に何を貼るか?を設定出来るのですが、複雑さを避けるため全面同じ画像を貼ります。
あとは、2重ループで1個づつCubeを配置してずらしていきます、このとき、出来たらXMLで書いた通りの順番に配置していきたいので、for文はデクリメントで回していきます。
csvデータの様に、カンマ(,)区切りなので、splitして配列に直していきます。
6列×5行なので、合計30回のループですね。
後で衝突判定用に別途配列wallArrayを作成して、マスが0の場合通路なので、Cubeは作らずに
wallArrayにはnullを代入します。カメラがターゲットの向きを向きっぱなしにしたいため、三角関数atan2を使ってやっと出来たんですが、Papervision 3Dにはカメラにtargetって便利なプロパティがあるのを知らず、一生懸命計算してました。
衝突判定でまずやるべき事は、紙飛行機にどの壁(Cube)が当たっているか、とりあえず最も簡単なやり方、hitTestObjectメソッド(物理的にはこれではいけない場合もあるかもしれません)でいきます、先ほど作り直した配列内のCubeに総当たりで衝突判定をします。if文の条件ですが、配列にはCubeかnullが入っているため、まず配列に入っているオブジェクトの型はCubeなのか(nullじゃ無いのか)、それと、そのCubeが紙飛行機と衝突しているか、この2つがtrueの場合のみ、変数hitWallBlockに当たってるCubeを代入して、degreeLimitterメソッドを実行し、breakでそこでループ処理を中断します。

今回の移動制限の方法として、まず三角関数Math.atan2によって、紙飛行機と衝突している壁の距離が解るので、そこから2者の角度を出して180度逆の方向をはじき出します。
通常の移動量の分だけ、逆の方向にX,Z座標を移動させておけば、壁を突き抜けないようになります。
あと、3Dオブジェクトの移動はDisplayObject3DクラスのmoveLeft()などが使えるらしいんだけど、今回はそれを知らずにx,y,zで移動してしまいました。今日はとりあえずここまで。次回はColladaオブジェクトで迷路を徘徊したいです。
