iPhoneのブラウザ上で30FPS以上でヌルヌル動く3Dゲームを作ってみた
iPhoneでのCSS 3D Transforms利用の可能性を探るために、CSS 3D Transformsを使って3Dゲームを作ってみました。
javascriptによる3DゲームですがiPhoneのブラウザで結構スムーズに動きます。
デモページ
http://ndruger.lolipop.jp/hatena/20110705/css_3d_game/css_3d_game.htm
- 非対応環境の例
- Android
- 傾きがブラウザから取れないので動きません。
- iPod touch 第2世代 OS 4.2.1
- deviceorientationイベントが発火しないので動きません。devicemotionイベントは発火するのでそちらで回転の検出を実装するようにすれば動きそうですがまだしていません。
- Firefox
- CSS 3D Transformsに対応してないので動きません
- Android
ゲーム内容
- iPhoneを傾けて赤い立方体を転がらせて、ゴールである青い立方体まで移動させます
- 床にある穴に落ちるとゲームオーバーです
- ステージは2-4まであります
iPhoneのブラウザでの3Dゲーム作成の問題と解決
本ゲーム作成の動機です。
問題
手動でjavascriptでモデリングして3Dをcanvasに描画する場合でも、iPhoneのcanvasは描画する対象が多くなればすぐにFPSが下がるため、高いFPSを維持したまま全体を再描画するケース(視点移動など)に対応させることが難しいです。
CSS 3D Transformsによる解決
iPhoneはCSS 3D Transformsに対応しており、これを利用すると、ブラウザとその移植層の3D処理により高速な描画が実現できます。
例えば下記の例では、transformプロパティのtranslateを指定した300個のdiv要素の親を、フリックを使ってiPhoneでもスムーズに回転させることが出来ます。
CSS 3D Transformsを利用すれば、divを好きな角度に回転でき、位置もtranslate()を利用して再レイアウトなしで変更できます。
これにより、下記のdivを「ポリゴン」として利用して下記のようなことが実現できます。
- divを4個使って4角錐の実現(背景画像を利用すればdivを表示上3角形としても利用できます)。
- divを6個使って立方体の実現
また、上記の例のように、CSS 3D Transformsは祖先に適用させれば、その子孫全体が影響するため、3Dのモデルを扱いやすい形になっています(SceneJSのjsonツリーがDOMツリーになった感じです)。
よって、動かしたいグループには親要素を作って、それにCSS 3D Transformsを適応するとグループ全体が動きます。
本ゲームの実装説明
- 傾きの実装
- 端末の傾きによる赤いブロックの移動と回転
- ゲームオブジェクトの実装
- 上下左右の壁をそれぞれボックスとして作っています。1つのボックスは6つのdivから出来ています。
- 最初はシンプルに壁や床などもタイル単位でボックスにしてそれを敷き詰めようとしたのですが、動作が重くなったのでまとめてしまいました。
結果の考察
本ゲームにより、transformプロパティを指定しているdiv要素が少ない場合、transformの変更による3Dアニメーションは非常にスムーズに動くことが確認できました。
興味深いことに、CSS Animationでtransformプロパティを変更中に、メインループにて他の要素のtransformプロパティを変更すると、傾きの変更による表示が時々カクカクするようになりました。
そのため今回のゲームでは、青いブロックの回転もCSS Animationを使わず、メインループの中で回転するようにしています。
うまく使えばiPhoneのブラウザでスムーズに動く単純な3Dゲームがいろいろ作れそうです。ルーブックキューブとか。