2014年10月14日

JavaScriptでスマホゲームアプリを作る - Titanium + Platino編

ようやく15パズルのTitanium+Platino版が出来た。

Platino Game Engine


ソースコードはこちら。 https://github.com/mikehibm/15puzzle-platino


● Platinoプラグインの導入


プラグインの導入は至って簡単。トライアル版をダウンロードして解凍して所定のフォルダにコピーすればTitanium側で認識してくれた。

あとはプログラムの先頭に

var platino = require('co.lanica.platino');

をいれてガンガン使って行くだけだ。
BGMや効果音を鳴らす時は

var ALmixer = platino.require('co.lanica.almixer');

も必要。
さらにapp.jsなどで最初に一回だけ

ALmixer.Init(0,0,0);

を呼んで初期化しておく必要がある。最初この初期化をしてなかったせいで音が出なくて30分ほど悩んだ。


● まずはサンプルのソースを確認


Herlockと同じくPlatinoもドキュメントを見てもいまいち分からないので、最初はまずサンプルプログラムを全てダウンロードしてソースを熟読するのが良いと思う。


Flappy Birdや戦車ゲームのサンプルが面白いけれど、多分一番参考になったのは「Codestrong Shooter」というシューティングゲームのサンプルだ。


● マルチ解像度対応


サンプルプログラムのマルチ解像度対応がちょっと気に入らなかったので、自分なりに試行錯誤する必要があった。背景の画像などは全てiPhone5sの640x1136のサイズを基準にして作っておいて、端末の解像度に合わせて横幅を画面一杯にして縦が短い場合は上下が切れる様に調整した。ApplicationWindow.js の updateScreenSize 関数でその辺りをやっている。

スプライトなどを画面に配置する時は、横幅は常に640として固定値で指定して構わないのだけれど、縦の高さは端末によって変わるので、真ん中に寄せたいもの(パズルのピースなど)については中央からの相対指定として、上端または下端に合わせたいものはそれぞれ上端(y=0)または下端(y=画面サイズ)からの相対指定とする様にした。


● タッチイベント


画面に配置したSpriteのタッチイベントを取得するのが少々面倒だった。まず画面(Sceneオブジェクト)のタッチイベントを書いて、その中でスケールを考慮して座標を変換した上で Sceneの forwardTouchToSprites 関数を呼んでやる必要がある。


● 連続でアニメーションを実行


アニメーションは下の様な感じでTransformオブジェクトを生成して実行する形になる。
var transform  = platino.createTransform({
  duration: 500,
  alpha: 0,
  easing: platino.ANIMATION_CURVE_CUBIC_IN,
  autoreverse: true,
  repeat: -1
 });
sprite.transform(transform);
ただ、連続で複数のアニメーションを実行するための簡単な方法が標準では用意されていない。「Codestrong Shooter」のサンプルにもある通り、アニメーション終了時のcompleteイベントを拾って次のアニメーションを開始すれば良いのだけれど、非常に面倒だ。

そこで調べたところ下のモジュールを見つけた。


これを使えば例えば6個のアニメーションを連続で実行する場合でも下の通り簡潔に書くことが出来るのでとても便利だった。
highScoreTranstion = new Transition([
  { duration: 1000, x: CENTER_X-highScoreLabel.width/2, easing:   platino.ANIMATION_CURVE_QUAD_OUT }
  ,{ duration: 500, alpha: 0, easing: platino.ANIMATION_CURVE_CUBIC_OUT }
  ,{ duration: 1000, alpha: 1, easing: platino.ANIMATION_CURVE_CUBIC_OUT }
  ,{ delay: 500 }
  ,{ duration: 1000, x: game.screen.width*-2, easing: platino.ANIMATION_CURVE_QUAD_IN }
  ,{ duration: 1, x: game.screen.width*2 }
]);
highScoreTranstion.animate(highScoreLabel, -1);


● Androidでのフルスクリーン表示


Androidで実行すると画面の上部にタイトルバーが表示されてしまって困った。
とりあえず tiapp.xmlファイルに

<fullscreen>true</fullscreen>
<statusbar-hidden>true</statusbar-hidden>
<navbar-hidden>true</navbar-hidden>

と書いてみたけれども Android 4.4 では効果なし。調べると新しいAndroidではプログラム内で

   window.activity.actionBar.hide();

を呼ぶ必要があるという事だったのでその通りにしたら無事フルスクリーンで表示された。


● iOSとAndroidで微妙に挙動が違う所


TextSpriteを配置した時にiOSとAndroidで位置がずれてしまって困った。
どうもAndroidだとwidth,heightが自動では計算されていない(0,0になっている)みたいだ。これは platino.createTextSprite 関数を呼ぶ際に明示的に widthとheightをセットする事で解決した。

他に、Androidだと微妙に処理が遅いのか少しカクカクした感じがしてしまう。上にアップした動画でも雲の動きがちょっとカクカクしているのが分かるけれど、iOSだともっとスムーズに動いた。Titanium + Androidでは前にも、「今ひとつどうもな〜」という経験をした事があるので、今回もやっぱりそうかという感じはある。


● ソースコード


今回のソースコードはこちら。
https://github.com/mikehibm/15puzzle-platino


● 一応の結論


Titaniumでのアプリ開発をずっとやっている人で、「ゲーム開発にもTitaniumを使いたい!」と言う場合には良い選択肢かも知れない。

あとドキュメントの中の下のページはすごく参考になった。

http://docs.lanica.co/docs/#!/guide/javascript_best_practices
配列をクリアする時は
myArray = []; 
ではなく
myArray.length = 0;
と書いた方が良い、とか。