回線の遅さについて考えていたらenchant.jsの機能追加を思いついたのでpull requestを送ろうとしたのですが、現状を鑑みるに優先度が上がらない(他に書くべきコードがある)のでアイデアだけここに残しておきます。ゲーム開発者の参考になれば。
問題提起:UXにおける素材数とレイテンシの問題について
HTMLゲームには、素材を増やすとゲームの起動が遅くなるという悲しい問題があります。素材のダウンロードに時間がかかるためです。昨今は商用ゲームでも起動を待たせるものが多い*1のでもしかしたら大多数のユーザーにはあまり問題にならないのかもしれませんが、特にカジュアルゲーム*2では重要な問題ではないかと思います。
ダウンロードにかかる時間はざっくりレイテンシとスループットに分けられると思いますが、スループットは3Dとかフルボイスとかやらない限りはまぁ無視できることが多いでしょう。問題はレイテンシです。特にクラウド化でサーバーが遠くにいることが多いことや、地球の裏側から遊んでもらえる可能性があることが、この問題を大きくしています。
従来の解決策:ファイルの結合(CSS Sprite etc.)
この問題を解決する方法としてWebサイト作成で使われるのがファイルの結合です。
詳しい話はハイパフォーマンスWebサイトあたりを参照していただくとして、ここでは「何回も行ったりきたりするのが悪いんだから1回で済ませればいいんじゃないの」という話だと理解していただければOKです。例えばスタイルシートやスクリプトといったテキストファイルなら、すべてくっつけて1ファイルにしてしまえば1回のダウンロードで済みます。
HTMLゲームでももちろんこの手法を使えます。JSファイルが10近く増えている場合などはこれを1つにするだけでも起動が目に見えて速くなると思いますので、まずはYUI CompressorやCoffeeScriptの--joinオプションあたりから試してみてはいかがでしょう。
従来の解決策の課題:画像と音声
テキストファイルの結合は上述のような手法が確立されているので、それを使えばいい話です。問題は画像と音声です。
画像の結合(CSS Sprite)はよく知られた手法なのでツールも整備されていますが、ゲームに組み込む=JavaScriptから触るのはややこしいんじゃないのかなぁというのが私の印象です(要検証)。カジュアルゲーム作るのにそんな物々しいもの必要だろうかとも思いますし。
音声ファイルの結合については、少なくとも私は聞いたことがありません。どうなんでしょう。
アイデア:「zipでくれ」
今回思いついたのは、画像と音声をひっくるめてzipにするという手法です。zipファイルをサーバ上にあらかじめ置いておき、ゲームプログラム(JavaScript)からダウンロードして解凍します。enchant.jsに組み込むなら以下のようになるでしょう。
game.preloadPackage('preload.zip'); game.onload = function() { var image = game.assets['bear.gif']; // gif file in preloaded zip file game.loadPackage('asyncLoad.zip', function (path) { console.log(path + ' is loaded.'); }); }; game.start();
1つのファイルにまとまってくれればtarでもなんでもよかったのですが、zipが最も無難といいますか、パッケージを用意するプロセスが一番楽そうだという期待があります。画像や音声は既に圧縮されていることが多いはずので、このプロトコル選定はわりとどうでもいいでしょう。
JavaScriptでzipを展開するライブラリはいくつかあるようですが、ライセンスが明記されているのはこれくらいでしょうか。これとか使いやすそうなんですが。
課題
- そもそもレイテンシがストレスになるケースがどの程度存在するのか
- 中国ではわりと……
- レイテンシを小さくする方向の努力(CloudFront etc.)の方が効果的ではないのか
- 個人が気軽に利用するにはまだ難しいのではないか
- 「それHTML5のオフライン機能でいいんじゃね」の可能性
- 初回ロードくらい我慢するよ、という人が多い可能性
でもカジュアルゲームにリピーターがつく可能性って- それにfirst impressionは重要
- モバイル端末のCPUでJavaScriptがzipを展開するのがどの程度現実的なのか
個人的には最後の課題が気になります。モバイル端末にどこまでやんちゃさせられるのか。さすがにもう大丈夫なんじゃないのと思う反面、要求メモリが厳しいかなぁという不安があります。
あとenchant.jsに機能追加する際の根本的な問題として、enchant.Surface.loadとかを書き換えなくちゃいけないと言うか素材ファイルのバイナリデータを自分でハンドルしなくちゃならないというややこしめの問題があります。
Data URIを使えばそこまで作り直す必要はないんでしょうが、Java開発者としての勘が「メモリが危ない!」と言ってます。JavaScriptの動作環境は正直詳しくないんですが、ちょっと長い文字列を生成してもOutOfMemoryErrorになったりしないんでしょうか?この辺はもうちょっと詳しくなりたいですね。