主にStage3Dまわりの作業ログ

=前置き=

 スマホ用のローグライクを作るにあたり、色々な部分で詰まったのでそこら辺のメモをしておく。
 予定が押してしまったので、ローグライクのUPは来週末になる予定。

Away3Dを使った際にスマホだけハング=

 Stage3D(というかAway3D)を使った際に、スマホ版だけハングすることがあった。
 原因は単純に「view.render()が呼ばれていなかった」というものだったので、表示の更新がない際もちゃんと呼ぶようにして修正した。「renderがupdateっぽい処理を兼ねている」ことや「PC上(厳密にはおそらくGPUエミュモード)では問題ない」ことなどでやや気付きにくい問題だった。


 追記:「Stage3D 利用時には、Context3D.present() が呼ばれないと、画面が一切更新されない」のが原因のようです。(9ballsyndromeさんありがとうございます)
→参考URL:AIR 3.2 でデバイス向け Stage3D コンテンツを作成するときの注意点 - akihiro kamijo

Away3Dのカスタマイズ時の注意点=

 可能であればCPU(汎用の処理)だけで作りたかったが、地形の部分暗転処理などがどうしても重くなってしまったため、そこら辺の処理をGPU(描画専用処理)に移行することにした。普通にStage3Dを使っても良いくらい単純な処理ではあったものの、将来的な拡張に備えてAway3Dで置き換えた。

 暗転処理のためにDiffuseMethodというものを書き換えたものの、ここで一部誤解しながら進んで詰まってしまった。誤解というのは「定数を設定してからコードが生まれるはずだ」というもので、シェーダ用のコードが生成される段階ではすでにどこにどの定数を設定するかが決まっているものだと思っていた。
 だが実際には「コードの生成時点でどこに定数をセットすべきかを計算している」という状況で、その情報を元にあとから定数を設定していた。

 もう少し具体的に言うと、getFragmentPostLightingCodeなどでコードを生成する際、regCache.getFreeFragmentConstant()で参照する定数を決定しつつ、その情報をvo.fragmentConstantsIndexに渡し、activateにてvo.fragmentData[vo.fragmentConstantsIndex+0]などに定数を設定するという流れになっていた。

=Stage3DとscaleMode=

 FlashAir)で作ったものをスマホで表示する場合、普通は「stage.scaleMode = StageScaleMode.SHOW_ALL」と設定するだけで良い感じに自動で画面に合わせてスケーリングしてくれる。しかしStage3Dを使う場合、このscaleModeが上手く機能しないっぽい。

 ということで、今回は「stage.scaleMode = StageScaleMode.NO_SCALE」と「stage.align = StageAlign.TOP_LEFT」を設定しつつ、自前で「stageWidth / VIEW_W」などのスケーリングを計算してフィットするように設定した。

=スケーリングとscrollRect=

 で、上のように独自スケーリングを行うと今度はscrollRect(表示領域の指定)との兼ね合いで問題があった。

 scrollRectを使う場合、「もとのSpriteのx,y:表示位置の左上の座標」「rectのw,h:表示のサイズ」「rectのx,y:表示の際のオフセット」という感じになるのだが、後者2つは「〜/scaleX」などでスケーリングを相殺しないといけなかった。

=予定=

 ローグライクに必要な機能はほぼ対応が完了した。あとはエネミーなどのバリエーションを増やしたり経験値やダメージの調整をしつつ、画像を正式なものに対応すればUPできる。ここら辺の対応にもうちょっと時間をとりたいので、今のところ来週末のUPを予定。動作確認はまだしていないけど、iOS側でもおそらく動くのでそちらも合わせて申請をする予定(ただし審査が行われるまで一ヶ月くらいかかりそうなのでAndroidを先に公開する予定)。