こんにちは。システム本部プラットフォーム部の坊野です。
前回、前々回とHTML5ゲームができるまでの過程における「描画の高速化」を解説してきました。
今回はHTML5ゲーム起動時の高速化手法についてお話しします。私たちのHTML5版「Blood Brothers」はアプリケーション版のようにインストールする必要はなかったのですが、アプリケーション版と比べて起動が非常に遅いという問題がありました。
今回はこの問題を解決するためにどのような処理を行ったのかお話します。
HTML5ゲームの起動
1.まず私たちのHTML5版「Blood Brothers」の起動の流れを説明しますと以下のようになります。
Mobageのログインページでログインします。
2.「Blood Brothers」のページに遷移し、アプリケーション (JavaScriptファイル) およびロード画面を表示するのに必要なリソース (テキスト、Webフォント、画像ファイル) をロードします。
3.ロード画面を表示し、ゲーム起動に必要なリソース (画像、音楽ファイル) をロードします。
4.ホーム画面を表示します。
これらの起動処理を時系列で表示すると図1のようになります。
図1 HTML5版「Blood Brothers」の起動処理
このように私たちの試作品は起動時に大量のデータロードが発生しており、これによって起動に非常に時間がかかるという問題がありました。また、テキストファイルに関しては起動時に復号化をおこなう必要があり、この復号化処理に非常に時間がかかっているという問題もありました。残念ながら当時のHTML5版「Blood Brothers」はこの復号化処理中何も表示できなかったため、この復号化処理時間の問題は非常に重大な問題でした。
リソースファイルの最適化
ゲーム起動の高速化にあたり、私たちはまず「Blood Brothers」がどのようなファイルを起動時にロードしているのかを調査しました。アプリケーション版「Blood Brothers」はそもそもスマートフォンにインストールされることを想定しており、起動時にこれらのリソースをロードしていたためです。
ですから、これらのリソースのうちホーム画面の表示に関係ないもののロードを省略することによってゲームの起動時間の短縮が可能になると考えられます。調査の結果、図2のように読み込まれた画像や音楽ファイルのうちは12%しかホーム画面では利用されていないことがわかりました。
図2 ホーム画面で利用されているい画像の割合
このため、これらのリソースの読み込みを省略することにより図3のように30%程度の起動時間の短縮に成功しました。とはいえ、依然として起動時に複数のファイルをロードする必要があったためアプリケーション版とくらべるとまだ起動が遅いという問題がありました。このため、私たちはHTML5の技術をもちいてリソースのキャッシュをおこなうことにしました。
図3 最適化後のHTML5版「Blood Brothers」の起動処理
Application Cache
まず、私たちはHTML5のApplication Cache APIを用いてリソースのキャッシュをおこなうことにしました。Application Cache APIはそもそもWebアプリケーションをオフラインで動作させるためのAPIなのですが、オンラインWebアプリケーションも以下のようなmanifestファイルを利用することによって必要なリソースをブラウザにキャッシュすることが可能になります。
CACHE MANIFEST # v1.0 / 2004-05-30 CACHE: /index.html /application.js /audio/bgm_001.m4a /fonts/BBJP_Font.otf NETWORK *
私たちはこのApplication Cache APIを用いることによってアプリケーション版並に起動時間を高速化できると期待していたのですが、残念ながら結果は期待したほどではありませんでした。
まず、テキストファイルに関してはApplication Cache APIによってキャッシュされるのはサーバにあるファイル、つまり復号化処理前のファイルとなります。ですから、たとえこれらのテキストファイルがキャッシュされていたとしても、HTML5版「Blood Brothers」は毎回これらのテキストファイルの復号処理を行う必要があるため、テキストロード・復号時間はほとんど変わらない結果となりました。
また、画像ファイルに関してですが、ホーム画面で表示されるのはキャラクタ画像などユーザ依存のものがほとんどを占めており、これらのユーザ依存の画像のキャッシュは共通のmanifestファイルを用いては困難です。また、この共通manifestファイルにホーム画面で使用しない画像ファイルや音楽ファイルが入っていた場合、ブラウザはこれらのファイルも初回起動時に読み込んでしまうため、残念ながらmanifestファイルによってはむしろ初回起動が遅くなるという結果にもなりました。
Web Storage
このようにApplication Cache APIは私たちの要求を満たすものではなかったため、私たちはWeb Storage, Indexed Database API, Web SQL databaseなどのHTML5 APIを用いてリソースのキャッシュを作成することにしました。このキャッシュはリソースのURLをキーとしたデータベースであり、以下のような手順で復号後のテキストファイル保存します。
1. XMLHttpRequestを用いてテキストファイルを読み込む
2. 読み込まれたテキストデータを復号
3. データベースに書込
このようにして復号後のテキストファイルをキャッシュすることによりテキストファイルのロード時間の短縮に成功したのですが、残念ながら上記のAPIは文字列しか扱えないため画像や音楽などのバイナリファイルをそのままキャッシュできないという問題がありました。
この問題を解決するため、私たちはXMLHttpRequest Level 2とData URI schemeをもちいることにしました。
XMLHttpRequest Level 2はXMLHttpRequestのHTML5における拡張機能で、サーバから受信するファイルの形式を指定することができます。たとえば、以下のコードのようにresponseTypeとしてarraybufferを指定するとPNGファイルのバイナリデータをそのまま取得することができます。
var request = new XMLHttpRequest(); request.open( 'GET', 'http://www.w3.org/html/logo/downloads/HTML5_Logo_32.png') request.resposneType = 'arraybuffer'; request.onload = function(event) { var data = new Uint8Array(event.target.response); ... }; request.send();
またData URIはRFC 2397で定義されたバイナリデータをHTMLやSVGのタグに埋め込むための規格です。たとえば、以下の2つの<img>タグはまったく同じ画像をあらわしています。
<pre class="prettyprint"> <img src="http://www.w3.org/html/logo/downloads/HTML5_Logo_32.png"/> <img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAtJJREFUeNrMV09r1EAUf/nnYduypWARaUEQ2+LJPehR1w8gevWi+wFavBTBm55EQVQUr3a/QUXwJu0qXuph48ltPdhqq6IVtrpsW5PMOJOdZGeymZ1JWqUPHpkMk/d+8/4HQE5lwpg9b7J19Ix4gVtfIvwxca4MCjJBTfcJX2XrRcJz3LrKnXtK+BhkJB0ApzjBvNIaB6ZJeFjybbkfMB0A5wnfUpxxGZgHKdajbqrIPrQUgrfYrekN19ia318lbDBrUJC73Lk1tl/jzh48MpIb6xcmKlzQ7TdVx56vzPEbdsqhpk765KSHyQ0ZAG0aOmIpz+xsIfC2caps83/4GQXZ6oD7D7G4yiBkgYhjhFMlcK4/TpXmOA4Ui0Wptva9CvjLS9D6HgBGACQAjcwuwJvfcl83+Py+IwNlL8WLXQBfcwPA7d+pMlVZ0Je8u9OAGvVwTcueociC4A/O1YyEdMGfPuxHADazWOAd6+8dANutOFqN8RMxasMwwR49JDH/LxIDjaTMvbvAvnxNyIKCJAt89yW0n8wQF+SbB4TOhZnPs2VAo69MlQVEACQT0HIviMCyIRgZ7N5mbAqMwpDoCoxzARAVvXkRck9GUAFcFgzMVsGaOC2kYOApXKpjAb4aUkt4d6bV9X+9oVXiU2OAlEzp9GKSLJCOV+z2ggsCHMls5nYBbre6L4VBcGZuh8UI1V+DNT5CFJ8Be1JUjjY3lJ1QBcBlU21PITJLZ0N2rszCgCQN0c8NrQ5r6lYuVH+lnYK0BoTf+Fg55GgXIu/Rje7tSVCakyWA4yfjnA9WlkjrfRsrV3VBHQC1tNmQWiKyhn/4KFijdtLcMll7s0Cqn398AWRZicLT6YD+DlZ2Qp0gjAOxLxCfKiRu2sWAPCyTo/dfkDKeDbPOeI49hX9A0hCTvl5lwwc1+7ws/7UBpACKfjgvcjFCFT6jT6Iw01D7V4ABALvsF7lgQK5jAAAAAElFTkSuQmCC"/> </pre>
これらの技術を用いて、私たちは以下のような手順で画像ファイルや音楽ファイルをデータベースに保存することにしました。
1. XMLHttpRequest Level 2を用いて画像ファイルおよび音楽ファイルをバイナリ形式で読み込む
2. 読み込まれたバイナリデータをData URIに変換
3. データベースに書き込み
このキャッシュを用いることによって、ユーザ依存の画像ファイルや復号後のテキストファイルをブラウザにキャッシュできるようになり、図4のようにHTML5版「Blood Brothers」の二回目以降の起動時間は劇的に向上し、ついにアプリケーション版とほぼ同等になりました。
図4 キャッシュを用いたHTML5版「Blood Brothers」の起動処理
サンプルアプリケーション
今回はこのキャッシュの動作を説明するためにサンプルアプリケーションを作成してみました。このアプリケーションはXMLHttpRequest Level 2で画像を読み込んでData URIに変換し、Indexed Databaseにキャッシュするものです。また、読み込んだ画像の色を変化させたり、ぼかし処理を適用することもできます。
次回はこのサンプルアプリケーションを用いて画像ファイルのキャッシュや画像処理について詳しく説明しようとおもいます。