このページは、クロノス・クラウン合同会社でi-appliを作った際に参考にしたサイトのリンク集および、柳井が得た知識をまとめたページです。開発に役立つ情報などをまとめておきます。開発担当の柳井が忘れないための覚書です。
開発環境の導入に関して分かりやすく書いています。
公式。必要なツールやドキュメントが入手できます。ドキュメントは全部読む必要があります。拡張APIに関するドキュメントは読む必要はないです。
基本APIでも機種によって使えなかったり、機種によって挙動が違っていたりするので、注意が必要です。
Java本体です。
必須ドキュメントです。リンク先ページ内を「Japanese」で検索すると当該ファイルが見つかります。
そらみのJ2MEゲームプログラミング以外にも、有用な情報が多数掲載されています。
i-applを中心としたMLの過去ログがまとめられています。過去ログを漁ると、有用な情報が出てくるので重要です。
サンプルが分かりやすく紹介されています。
細かなテクニックが掲載されています。
Jarファイル容量削減ツール。5%ぐらい軽くなります。結局めぐりめぐって、これを使いました。
私の場合は、これと自前の定数埋め込み化ツールを使って、大幅に容量を削っています。2つ使うと10%(30KB→27KB)くらい軽くなります。
実践的なプログラミング例が掲載されています。
軽量化についてまとめられています。
公式より充実しています。
「DoJa2.0対応端末の待ち受けボタン・トレースの表示」に、トレース情報の出し方がまとめられています。トレースは、実機で標準出力を実現するための機能です。504から搭載されました。トレースは、i-appliのjamファイルでトレース情報をonにすると利用できます。
DoCoMo公式。基本的な情報しか載っていません。
i-appli用ベンチマークソフトの結果がまとめらています。各機種での処理速度の違いを調べたい時に役立ちます。
機種依存情報付き言語リファレンス。何気にクリティカルな情報が見つかることもあるのですが、あまり使いませんでした。
505系のi-appliを作る上での注意点がまとめられています。505系は504系よりも相対スペックが低いので注意が必要です。
具体的に言うと、画面サイズが4倍になったのに、CPUは早くなっておらず、メモリーもそんなに増えていないので、相対スペックとしては1/4程度に落ちてしまっています。
Javaで分からないことがあれば、ここにくればたいてい分かります。ただし、サーバーが落ちていることが多いので、急ぎの時には使えなかったりします。
ネット上からJDK1.4のドキュメントを全文検索できます。かなり便利です。何気にローカルよりも早いです。
ここも基本的な情報を入手できます。
GIFファイルを直接解析したりするプログラミングを書く時に必要になります。
Javaでは、変数やメソッド、クラスを定義すると、それらに伴う初期情報が色々と付加されます。
そのため、変数やメソッド、クラスの数を減らせば大幅にプログラムは軽くなります。減らせない場合でも、極力初期情報が伴わない形で定義することで、プログラムサイズを小さくすることができます。
また、アプリ本体で持たなくてもよい情報は、極力外部に持つようにします。
クラスの数は少なければ少ないほどよいです。クラスを1つ定義すると、Jarファイルの状態で2kbぐらい重くなります。i-appliでは、クラスを極力使わないプログラムを書く必要があります。
メソッドの数は少なければ少ないほどよいです。メソッドを1つ定義すると、Jarファイルの状態で10~20byteぐらい重くなります。ただし、メソッド化することで、よりサイズが小さくなる場合はこの限りではありません。プログラム内で共通部分が多い場合はメソッド化した方が軽くなります。
メソッドは可能な限りstaticにする必要があります。これだけで1つのメソッドにつき、10~20byteぐらいは軽くなります。
また、入出力が似ているメソッドはまとめてしまい、複数機能のメソッドにすると軽くなります。
グローバル変数は、public staticにする必要があります。これだけで1変数につき5byteぐらいは軽くなります。
グローバル変数は極力数を少なくする必要があります。配列化して変数の数を減らすとよいです。
ただし、プログラム中で配列内の値を定義してはいけません。プログラム中で配列内の値を定義した場合、それらは1つずつの別の変数とみなされて、初期情報が付加されます。
配列の中身はプログラム的に生成するか、外部ファイルから読み込んで代入すると劇的に軽くなります。
ifはswitchより軽いです。また、if elseの構文より、if ifの構文の方が軽いです。a ? b : cの構文は、内部的にif elseに展開されるので重いです。forも重いので、まとめられる所はまとめた方がよいです。
if 1つにつき、Jarファイルの状態で5byteぐらい重くなります。ifは極力使わないようにするとよいです。
例えば、aが0~5の値を取るとして、
if ( a > 3 ) {
b = 90;
} else {
b = 10
}
といったプログラムは、
b = 10 + 80 * ( a / 3 )
と書くと10byteぐらい節約できます。
文字列やデータは必ず外部ファイル化します。そのため、スクラッチパッドやネット上のリソースをDLするためのファイルシステムをまず構築する必要があります。
文字列は言語ファイル化して持ちます。
配列データは、外部からバイナリ配列として読み込みます。
504以前は圧縮ファイルの解凍メソッドがないのですが、自前で解凍メソッドを組み込むとデータを多く詰め込むことができます。
Jargやレトロガードなどの、難読化ツールを使うと5%ぐらい軽くなります。
また、定数は定数埋め込みツールを作ってコンパイル前に適用することで5%ぐらい軽くなります。
i-appliは機種依存が甚だしいです。その中でもゲームにおいて重要になるのが、グラフィック関係の機種依存です。以下、グラフィック関係の機種依存を中心に触れていきます。
D50xとN50xでは、メモリがJavaヒープとネイティブヒープとに分かれています(その他の機種はメモリは1つだけです)。
Javaヒープとは、Javaのオブジェクトなどが格納される領域です。ネイティブヒープは、画像などのメディアリソースが格納される領域です。
このメモリが分かれていることによって、メディアデータを多く使うゲームアプリでは、問題が発生します。どういう問題が起きるかと言うと、開発環境ではメモリが十分に足りていたのに、実機に移すとメモリが足りないという問題です。
これは、ネイティブヒープが、主に画像によって食いつぶされてしまうことで発生する問題です。
また、機種によって同じクラスを初期化しても消費メモリーの量が違います。
さらに、メモリサイズを取得するメソッドでは、どうもJavaヒープの値しか取得できないようで、ネイティブヒープでどれだけメモリを使ったが分かりません(これは私が気付いていないだけの可能性もありますが)。
そのため、実機で動かすまで、メモリが本当に足りているかどうかは分かりません。
実機では、こういった制限があることを、念頭に入れておかなければなりません。
Dでは、Imageクラスを作る時に、画面より大きなImageを作ることができません(ゲームでバッファを作る時に困ります)。
また、グラフィック用のメモリー領域が他の機種より狭くなっています。そのため、Imageクラスを作ると、このメモリー領域を真っ先に食いつぶします。
さらにDでは、他の機種に比べ、同じサイズのImageクラスを作った場合のメモリーの消費量が激しく多いです。
そのため、結果的にDだけ凄い少ない量しかImageを持つことができません。
端的に言うと、画像の先読みをしようとして、ある程度の画像を読み込んでおくような処理をすると、Dだけエラーで落ちます。
以下推測です。多分、Dでは内部的にImageの持ち方にバグがあって、非常に多くのメモリーを消費してしまうのだと思います。そのため、そのバグを隠す目的で「画面より大きなImageを作れない」という特殊な条件を「仕様」として謳っているのだと思われます。
N505では、ファイルをDLした時とそうでない時では、ネイティブヒープの使用量に違いがある可能性があります。
N505では、ファイルをDLした直後に画像をImageとして読み込んでいると、ある程度の画像を読み込んだ時点で「Out Of Memory Err」が発生します。しかし、同じ量の画像を読み込んでも、ファイルをDLしていない時にはエラーが起こりません。ちなみに、DLした直後も、DLしていないときも、Javaヒープの使用メモリ量に差はありませんでした。
この現象に関して色々と実験した結果、以下の2種類のうちのどちらかの仕様になっているのではないかという推測に落ちつきました。
詳細は不明ですが、ファイルをDLした場合とそうでない場合で、ネイティブヒープの使用量に差がある可能性があります。
i-appli利用可能機種の中で、最もゲームに適した能力を持っているのはPシリーズです。ともかくPは早くて強力です。
そのため、開発時にPをデバッグ用のマシンにすると、他の機種で遅くなり過ぎるという問題が発生します。逆に、他の機種でちょうどよいように作ると、Pでは速くなり過ぎる可能性があります。
速度が重要なアクション系ゲームを作る場合は、こういった機種の違いを把握しておく必要があります。
i-appli利用可能機種の中で、最もゲームに適さない描画能力を持っているのはNシリーズです。ともかくNは遅いです。
どこが遅いかと言うと、描画時間分解能が、他の機種に対して著しく劣っていることです。100msecに一回しか画面が再描画されないために、秒間10フレームが最大となります。そのため、まともなアニメーションはできません。
速度が重要なアクション系ゲームを作る場合は、こういった機種の違いを把握しておく必要があります。
505系は504系よりも非力です。何故かと言うと、画面サイズが縦横2倍の4倍になったのに、CPUはほとんど早くならず、メモリ量もそれほど増えていないからです。
そのため、画面バッファなどのImageクラスをたくさん作っていると、504から505に移植した際にエラーが出る危険性があります。
その対策として、505からは、小さな画像を大きな画像に拡大するメソッドが追加されたのですが、これははっきり言って使えません。機種によっては、0.5~2秒(聞いた範囲)も、そのメソッドの実行に時間がかかるそうです。
504、505対応で作る場合は、504を作って505に移植するという考え方ではなく、505も504も同時に実験しながら作るという考え方で作る必要性があります。