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

  • 動作環境
    • iPhone4 OS 4.3
    • Chrome14, Safari5
      • iPhone用ゲームですが、デバッグ用にマウスのドラッグでも操作できます
  • 非対応環境の例
    • Android
      • 傾きがブラウザから取れないので動きません。
    • iPod touch 第2世代 OS 4.2.1
      • deviceorientationイベントが発火しないので動きません。devicemotionイベントは発火するのでそちらで回転の検出を実装するようにすれば動きそうですがまだしていません。
    • Firefox
      • CSS 3D Transformsに対応してないので動きません

ゲーム内容

  • iPhoneを傾けて赤い立方体を転がらせて、ゴールである青い立方体まで移動させます
  • 床にある穴に落ちるとゲームオーバーです
  • ステージは2-4まであります

iPhoneのブラウザでの3Dゲーム作成の問題と解決

本ゲーム作成の動機です。

問題

まず、iPhoneは現在WebGLに対応していません。

手動でjavascriptモデリングして3Dをcanvasに描画する場合でも、iPhonecanvasは描画する対象が多くなればすぐにFPSが下がるため、高いFPSを維持したまま全体を再描画するケース(視点移動など)に対応させることが難しいです。

CSS 3D Transformsによる解決

iPhoneCSS 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を適応するとグループ全体が動きます。

本ゲームの実装説明

  • 表示されているFPSは、赤い立方体の移動のループのFPSです。
  • 端末の傾きによる赤いブロックの移動と回転
    • 上で取得した回転はクォータニオンなので、回転行列を経由して、オイラー角(x,y,z)に変換します
    • オイラー角(x,y,z)の回転から、x,y軸の傾きを使って移動方向・移動量・回転量を決めます
  • ゲームオブジェクトの実装
    • 上下左右の壁をそれぞれボックスとして作っています。1つのボックスは6つのdivから出来ています。
    • 最初はシンプルに壁や床などもタイル単位でボックスにしてそれを敷き詰めようとしたのですが、動作が重くなったのでまとめてしまいました。

結果の考察

本ゲームにより、transformプロパティを指定しているdiv要素が少ない場合、transformの変更による3Dアニメーションは非常にスムーズに動くことが確認できました。

興味深いことに、CSS Animationでtransformプロパティを変更中に、メインループにて他の要素のtransformプロパティを変更すると、傾きの変更による表示が時々カクカクするようになりました。
そのため今回のゲームでは、青いブロックの回転もCSS Animationを使わず、メインループの中で回転するようにしています。

うまく使えばiPhoneのブラウザでスムーズに動く単純な3Dゲームがいろいろ作れそうです。ルーブックキューブとか。