NME で WebP 画像を使えるようにしてみた

NME でゲームを作った時、画像リソースを全て png 形式で持たせていたが、個人的にやりたいと思っていた WebP 画像対応をしてみたのでその辺の話を少し書こうと思う。

まだゲームを作り始める前まで話は遡るのだが、実はマルチプラットフォームでゲーム作るどころかゲーム自体を作ったことがほぼなかった(唯一まともに作ったことがあるのはこれだけだ)し、スマートフォンアプリも作ったこともなかった。
わりと何から始めたらいいのかわからない中で早い段階にぶち当たった壁はこれ。

■ 多種多様な画面解像度に対してどう向き合うのか

まあ誰でも通る道なんだろうけども、全ての環境でそれなりに使えるようにする方法を考えてみて、何か現実的な妥協点を見つけて後は辻褄を合わせる方向にするしかなさそうだという結論に。

そもそも「全ての環境」って何だ? どこで動くんだ? という点が見えてきたので、まずは最低限動かしたい環境をザックリでいいから決めることにした。
  • iPhone(パフォーマンスで問題が出なければ 3GS ぐらいまで)
  • iPad1, iPad2, 新しい iPad
  • Android 系統は色々ありすぎるので取りあえず手元にある Galaxy Nexus で動作確認
  • Android タブレットでも動かしたい
  • Flash or HTML5
  • Windows / Mac
少ない人数で作るのにも関わらず欲望が溢れてなんか結構な数になってしまった。
この中で大きい表示になりそうなのは 新しい iPad で、2048x1536 とかいう気が狂いそうなレベルの大画面だから、取りあえずこれを基準に作っておけば何とかなるんじゃね? ということで今回はこの画面解像度を基準に素材を用意していくことにした。

ただし、メインのプラットフォームは恐らくタブレットではなくスマートフォン、あるいはブラウザになることが予想された。そのため縦横比については iPhone を基準にして、960x640 の長い方を 2048 にした時の大きさである 2048x1365 をゲームの表示エリアとした。
例えば 新しい iPad の場合は 2048x1536 なので、85~86px の黒枠を上下に設けて辻褄を合わせることになる。
(別に黒枠じゃなくてパターンとか何でもいいけど)

この辺を Apple 製デバイスを持っていないので妄想しながら決めた。
指の移動距離などの関係も考えるとゲーム性を損なわせない対応をするためには本当は dpi も考慮しなければいけないと思うが、そこまで手をつけると画面寂しくなったり大変そうなので今回は見送った。

■ スマートフォンは縦長、PC は横長、タブレットはどちらでも

アプリが動作する環境で頻繁に使われる向きでゲームがプレイできた方がいいと考えて、ポートレートとランドスケープの両方に対応できるように作ることにした。
今回は横スクロールアクションゲームなどではなく、どちらの画面でもゲーム性は大きくは変わらないからという理由もあった。

この時点で 新しい iPad では 2048x1536 と 1536x2048 で動作する可能性が出てきた。
そのため最終的には画面を覆うような素材に関しては 2048x2048 の正方形で用意する形へ。

元になる素材ランドスケープポートレート

このスクリーンショットは Galaxy Nexus 上で実際に動作しているタイトル画面だが、iPhone より少し画面が細長いため余ったエリアは黒く塗り潰されている。
そして、ランドスケープとポートレートの両方に対応して、背景画像の見える範囲が変わっている。

■ 実際の動作環境で 2048px も必要なケースはほとんどない

一番大きい画面の環境を基準にデータサイズを定義したので、当然ながら実際に必要なサイズより全般的に大きな素材ばかりになった。
実行時に毎フレーム画像を縮小するのはコスト的にもメモリ的にも無駄になりそうなので、ローディング画面では読み込みと縮小を同時に行うようにした。

これによってローディング画面は少し長くなってしまったものの、どの環境でもある程度綺麗な画面で表示できるようになり負荷的なデメリットもなくレンダリングできるようになった。

■ 最後に残った問題

当然大きめの画像を大量に抱えることになったので、アプリケーションの全体容量が大きい。

ノイズを嫌って JPEG にできそうな画像も PNG で用意したとか、NME 側の PNG 読み込み処理のバグで元々考えていた最適化が使えなかったなど原因は色々あるのだが、原因はさておきゲームのボリュームの割にはアーカイブが大きくなってしまった。

そこで WebP を使ってみようかな、と思った。

WebP は発表された当初は WebM のイントラフレームをそのまま画像として使えるようにした簡単なファイルフォーマットだったのだが、途中でロスレス形式とαチャンネルの機能が追加された。
これによって JPEG のように非可逆でありながらαチャンネルを持たせることができ、小さいファイルサイズで半透明の画像を扱うことができるようになった。
絶対にノイズを乗せたくないような場所であれば画像自体にもロスレス形式を選べる非常に心強い存在だ。

しかし、NME は標準の状態では WebP 画像は読み込めない。
取りあえずのリリース目標日が迫っている中で立ちはだかった問題だったので最初のリリースでは PNG のままでリリースしたのだが、落ち着いたので改めて WebP 画像に対応させるため、NME のコードを弄って WebP 画像を使えるようにした。

記事の途中で例に出したタイトル画像は PNG で 3.60MB あったが、WebP にすると 207KB まで縮んだ。
さすがにじっと見てみると劣化している部分を見つけることはできるが、JPEG で同じぐらいの容量になるまで画質を下げると品質を 24 とかで保存しなければならなかったので、画質に関しては言わずもがな、という感じだろう。

一応サンプルとして実際に保存したものをわかりやすくトリミングしたものを用意した。

JPEG(208KB)WebP(207KB)

こんな感じで、容量の割には非常に鮮明で素晴らしい品質だと思う。

今回使用した全ての画像リソースを WebP に変換してみたところ、アプリの容量が 10MB 程度小さくなった。
この手の読み込み側の対応状況を気にしなくてもいい状況ではどんどん WebP を使っていきたいと思った。