CreateJSでゲームを作る


1年半振りにブログからこんばんは。

ちょっと最近の話題に合っていそうな出来事があったので書いて見ます。



自分の守備範囲は主にASですが職場では同じECMA Scriptって理由で結構前からJavascriptと戯れています。

ngCoreとかArcticJSとか使って色々とモバイルゲーム開発を行っていました。



時期も時期で会社も新体制になったりで色々と環境が変わりつつあって、

そのひとつに自社でJSライブラリを作ろうか。見たいな話があります。



個人的にはどちらでも良いと思ったのですが、

恐らく適当な返事をすると僕も(というか主に僕が)ひどい目に合いそうなので、

そもそもライブラリを作るとか以前に名のあるライブラリを試してりしてから

判断しても良いのでは無いかと打診したところ、

「じゃー 空いた時間で作ってみて。」
と言われてしまい先週から色々調べていました。



という訳で前から気になっていたEaselJS。ちょっと前からCreateJSの話題が飛び交っていて、

これを調べてみたらEaselJS以外にもプリローダー(PreloadJS)やサウンド(SoundJS)、

トゥイーン(TweenJS)等、便利なモジュールが揃っていたので、

どうせならまとめて全部試してみようという事で試してみました。



ArcticJSを使ったときに思い知らされましたが、

適当にサンプルを触っただけだとライブラリの癖や落とし穴、不具合等が見つけられません。

なので今回は「同じ目に遭わないようにある程度まともに動くゲームを作る」事を目標に開始。



先日WindowsPhoneSDKの環境構築のお願いをされた際に試したチュートリアルプロジェクトの素材が

手元に残っていたので2日くらい掛けてこれらを使ったゲームを作ってみました。

完成品はこちらで確認できます。



androidで見ようとしたらエラーが出ていました。('A`)

僕的には仕事(モバイル)で使えるかを確認したいのが目的なので、

タップや縦、横に傾けた際のリサイズ等の挙動を細かく調べていきたいと思います。

そのあたりは追々。

マップ実装


去年の6月に3Dの勉強始めるのに止まってたsalvageことsidestory'sですが、

3Dの勉強が落ち着いてきた(と言うかクリッピング放置のままフェードアウト)ので、

今年の2月頭からまたちょくちょくいじってたりします。



最後の更新から色々機能つけました。



・SharedObjectを使ってUIの位置情報を記録できるようになりました。

・全てのUIがドラッグできるようになりました。

・懲りずにホットバーを大改装しました。

・ホットキーとホットバーを完全分離したので、

 好きなスロットに好きなクラスの好きなアビリティーホットキーをセットできます。

・キャラクターをマウスオーバーすると簡易ステータスを表示するようになりました。

・ターゲットウィンドウを追加しました。

・グループウィンドウを追加しました。

・手抜きレーダーを追加しました。



・簡易敵AIを実装しました。

・フィールドを実装しました。

・アビリティーを生成する際に必要な設定ファイルの仕様が決まりました。

 (実装は出来てますが、設定ファイルが古いままなので要修正)



操作方法は多すぎて書く気になれないので、

ある程度遊べるようになったらまとめて書こうと思います。



せっかくマップ実装したので歩く方法だけ。

テンキーの5を押します。

キャラクターが全て集まったらシフトキー+W or S and/or A or dで移動できます。



サンプルはこちら。

重いので埋め込みフォントは消してます。

クリッピングの実装(途中経過)

赤・緑・青の三点から構成される面をポリゴンに、赤枠を描画領域に見立ててクリッピングを実装中。

デモデモ
■操作方法
(赤・緑・青の○Sprite)ドラッグ→特定の頂点移動

3頂点全てを同時移動
 テンキー8 → 上
 テンキー2 → 下
 テンキー4 → 左
 テンキー6 → 右

ポリゴン回転
 テンキー7 → 左
 テンキー9 → 右

ポリゴン伸縮
 テンキー+ → 拡大
 テンキー- → 縮小

※面は時計周りで構成されるので、
 右回りに赤→緑→青となるような場合のみ正常に判定できます。

                                                                                          • -



どうにかクリッピング後の頂点を求める処理がほぼ完成。
(クリッピングされた辺が2つの場合の場合分けがまだ未完成)

座標変換に始まりテクスチャマッピングやらシェーディング周りの実装を一通り勉強してきたけど、
クリッピングは今までで一番悩まされてる。

Flashでの3Dレンダリング手法がスキャンライン法じゃないとか、
クリッピングを自力実装してるプログラマの人口が絶対的に少ないとか、
色々と考えられるため参考になる資料が無いに等しい。

ので、どんどんスパゲティー的なコードになってってる・・・
クリッピング処理だけで既に500行超えしてるんですが(;´Д`)
取りあえず、クリッピング後の頂点数を求められるようになったら、
求めた頂点を使ってポリゴンを分解、各頂点の内積やUV値の補正を実装する予定。

クリッピングは地味な処理っぽく見えるけど凄く重要なのは分かった。
これが出来ないとワールド用の巨大六面体とか長細いポリゴンとか配置できないしね。
がんばろう。

クリッピングの勘違いに気づかせてくれたAlternativa3Dですが、
調べれば調べるほど凄い。クリッピングの正確さにも驚いたけど、
BSP-Treeってので深度管理してるのを知って更に衝撃。
というか、この単語自体初めて目にしたけど、
wiki曰くzバッファなしでも正確な深度管理ができるという…。
zソートなんて実装してる場合じゃなかったとしか言いようがないwwww
まぁ追々勉強するってことで…orz

そういった部分からみてもPV3Dよりも完成度高いですねぇAlternativa3D。
パッケージの中身もかなりシンプルだし。
しいて言うならライティング周り(影ではなく光源的な表現)がちょっと弱いのかな?という感じがする。
といっても影付けがかなり精巧だからそれでも十分だと思うけど。

多分ライセンス絡みでPV3Dより厳しいから皆使ってないんだろうなぁとも思ったり。

残すところはクリッピングのみ!


デモデモ
カメラの移動はW,S,A,D,Q,Eです。SHIFT押しながらだと移動速度速くなります。

更新点
・シェーディングを実装
 今までのデモではモデルに対してシェーディングとレンダリング(テクスチャ等)
 どれか一つしか選べなかったのですが、
 今回からレンダリングされたモデルに対してシェーディングする事ができるようになった。
 テクスチャ+グーローはもうそれなりに完成度高い3Dモデルに見えるんじゃないですかねw


・Zソートの改善
 前回と言うより、
 今までZソートはモデルの原点(またはレイヤー原点)のZ値による深度管理だと思っていたけど、
 どうやらサーフェイス単位でソートをかけると良いッぽい。
 (PV3Dのソートはサーフェイス単位でやってるみたい。)
 なので自前のエンジンもサーフェイス単位に変えてみた。
 前回までの酷いZ判定ミスもなくそれなりにしっかり表示されてる。
 ただ、失敗したときにポリゴンがかける感じですね。
 まぁZソートならこの辺りが限界なんでしょうね。


・アルファマッピングの対応
 前回のデモを見ると分かるんですが、
 モデルの頬の渦巻きテクスチャが表示されてません。
 これはアルファマッピング画像をテクスチャに反映させてなかったのが原因なんですが、
 その機能をつけたのでしっかり渦巻いてます。


・ライティング機能アップ
 今までは位置の変更のみしかできなかったのですが、
 シェーディングを実装したついでに光源にカラー情報をつけて
 そのカラー値でのライティングを出来るようにしてみました。


・UI復活
 FD環境のみでflパッケージ使う方法がわかったので復活です。
 ┗IDEコンポーネントを全部ステージにのっけてSWC書き出し。
  ┗SWCをFDプロジェクト内に入れてADD To Library。(便利すぎる!)


後はクリッピングのみ!

メタセコイアからのモデルインポートを実装(仮)

進展

1.今更ながらやっとFP10に対応。
FDでのtraceのやり方がよくわからない&手元にはCS3しかない等の理由から
今までFDとCS3で組んでたんですがどうしてもVectorクラスで実装してみたくて
FlexSDKとFDでFP10環境を整えてみた。traceも解決。

ついでにFlexで書き直そうとも思ってちょっとかじってみたけど途中で却下。
重い!重すぎる!ドキュメントを読んで思った。

「これはHTML(MXML)とJS(AS)のような関係なんだな」と。

表示オブジェクトの基本クラスがSpriteのサブクラスとか…
いらない機能多すぎで処理速度を優先したい時に使うものじゃないと思った。
なので、Flexじゃなく普通にFlashでコードを書き直し。
最新版のデモはflパッケージが使えなくてUI全消し!ヽ(`Д´)ノ

全ての配列をVectorクラスに書き換えてみた。
結果の程は?と言うとちゃんと調べてませんが変わらない!w
速くなったといえば速くなったのですが、
コードに変更を加えずにFP9からFP10にした時に重くなって、
コード書き直して速くなって結果どっこいみたいな・・・w
う〜ん よくわからんですねぇ。

Vectorへの要素追加とか取得をArrayと比べてみたけど変わらないような…
しかもキャストしないと速度上がらないってそれこそ配列と同じじゃないか!

使い方間違ってるのかなw
2.ロジック大幅変更
今までは最初に全ての頂点を座標変換させて
変換された頂点を使って法線を求めたりカリング判定したりしてたんだけど
今回からは逆にしてみた。

最初にモデルの座標が与えられた時点で面や頂点の法線を求めることが出来るので、
それらを最初に求めてしまう。
これをしておくと描画ループの中に法線を求める必要が無くなる。
(正確にはローカル座標系の法線にワールド回転行列をかけるだけで済む)

更に同じ法線をもつ面をグループ化しておくと。
カリング処理も速くなったり。

そしてカリング処理が先になったという事は
座標変換する頂点数の数が最大半分くらいまで減らすことが出来るという事。

しかしふたを開けてみるとカリングに一番時間かかってるw
これはもう少し書き直してみた方がいいかもしれないですね。
※追記
ブラウザ(プラグイン)での再生だとかなり早くなってる。
それなりのポリゴン数にも関わらずうちの化石PCでもFPS15でてるじゃないか!
遅かったのは開発にデバッグ版(スタンドアローン)使ってるのが原因なのかな??

それと行列を求めるコストも大きいのでクォータニオンでも試してみたかったり。
でもクォータニオンさっぱりわからないw

3.メタセコのインポート。
ローポリでそれなりにいい感じに見えるようなモデルを探してたらありました。
ズサさん@三次元CG@七葉から拝借しました。
ありがとうございます。

デモデモ
マウスとか移動に関しての操作方法は今まで通り。
UIに割り当ててた操作を一部キーボードに変更。
V : 頂点描画
T : テクスチャー描画
M : モデル回転
(シェーディングはロジック変更中なので未実装です。)
プレイヤー上に表示されているステータスの詳細は次の通り。
get Matrix : 最終的な変換行列を求める処理にかかった時間(ms)
zSort : Zソートにかかった時間(ms)
C : レイヤー内のポリゴンをカリングした際にかかった時間(ms)
T : レイヤー内のポリゴンを頂点変換した際にかかった時間(ms)
R : レイヤー内のポリゴンを描画した際にかかった時間(ms)
TOTAL : get MatrixからRまでのトータル(ms)
FPS : トータルをFPSに変換したもの

とりあえず頂点や面の情報をそのまま描画まで持って行ける所まで実装できた。
本格的なモデルを表示してみてわかったけど、Zソートが想像以上に使い物にならなかった。orz
PV3Dとかどうやって深度管理してるんだろ?というか描画に何使ってるんだろー。
これはどうにかしたい。
後はマスク画像とテクスチャのブレンド処理とクリッピング
ここここなど、良い資料が見つかったのでこれも実装したいですねー!
あぁ時間がいくらあっても足りないっ><

テクスチャーマッピングを実装


デモデモ


1週間挑んだけど結局自力で実装できなかった。。。ヽ(`Д´)ノ
なので困ったときのグーグル先生頼み(;´Д`)

参考ページ
http://www.adobe.com/jp/devnet/flash/articles/matrix_class.html
http://www.d-project.com/flex/009_FreeTransform/


1つめのリンクで紹介されている手段は、
画像データの領域全てを使用してポリゴンにマッピングするので
「面の数だけ画像が必要」とか「四角ポリゴンしかマッピングできない」とか
色々と不便なので2つめの手段を使わせてもらいました。
テクスチャとして使ってる画像はこんな感じのです。うさぎテラカワユス(*´Д`)

参考にしたソースの行列の使い方が衝撃的だった。
今までは一つ一つの変換行列を合成して使うものだと思っていたけど、
この使い方はいつか見た参考書のような発想で使ってるような気がする。
(って言うよりこれが本来の使い方なのかもしれないけど・・・w)
ある座標系から別の座標系に変換するって言うのはこういうことなんですかねぇ。
雰囲気でしか理解できてませんが、かなり良い刺激になりました。

実際の描画にはbeginbitmapfillメソッドを使用してますが負担は軽いです。
一番負担のかからない頂点だけの描画とFPSがそんなに変わらない。
画面いっぱいまでモデルに近づく描画する面積が広くなるからか一気に重くなりますがw

気づいてる問題はパースがきつくなった場合マッピングがおかしくなる点。
この回避方法は同参考サイトで解説されてるんですがこの回避を入れると、
最低でも4倍の負担がかかってしまうので入れる気になれませんでした。
やっぱ入れなきゃ駄目なのかなw

それとは別にある問題に気づいた。それはクリッピング処理!
思いっきり勘違いしてた・・・完璧とか言ってすいませんorz
この3Dデモワイヤーフレームを表示したとき勘違いに気づいた。
頂点が描画領域からはみ出たら新たな三角形を描画し直してる・・・
これどうやってるんだろ・・・

この辺りどうにかしたいですねぇ。
でもこればっかりはどうがんばっても今のスキルじゃ無理臭い。
断念してバンプマッピングとかメタセコファイル読み込みとかやろうかな・・・w