企画記事
「enchant.js」でゲームを作ろう! HTML5とJavaScriptによるアクションゲーム制作入門
enchant.jsがサポートしているHTML5は,長らく使われていたHTML4に代わる次世代Webシステムの要となるものです。HTML5ではWebページの動的な要素,とくにグラフィックスの描画機能などが大幅に強化されており,これまでFlashを使わないとできなかったようなことが,HTMLとJavaScriptだけでできるというのが最大の特徴となっています。
ここにきてInternet Explorer 9(以下,IE9)もようやく正式版がリリースされ,主要なWebブラウザでのHTML5サポートがほぼ出揃いました。今回はenchant.jsでのゲーム開発に当たってIE9を主に使っていきますが,基本的にはほかのブラウザでも大差はありません。IE9は,Windows XPなど古いOSでは動作しませんので,Windows XP以前のOSを使用している人はほかのブラウザを導入してください。
最初にお断りをしておきますと,私はJavaScriptのエキスパートではありません。むしろほとんど触ったことはありませんので,ときどきおかしな説明もあるかと思いますが,ご容赦ください。手探りで進めている状態であり,enchant.jsの全貌を理解しているわけでもありません。
また,今回解説するスタイルは,あまり一般的でない部分が多いかと思われます。enchant.jsは,JavaやJavaScriptのプログラミングに習熟している人はかなり簡単に扱えるようですので「サンプルもドキュメントもついているし,問題ない」という人は我が道を行ってください。プログラムの経験がまったくない人には,さすがにイチから説明するのも無理ですので,先にJavaScriptの入門サイトなどで勉強してください。ある程度の経験はあるけど「サンプルを眺めてみてもよく分からない」という人が今回のターゲットです。
「enchant.js」のダウンロードはこちら
enchant.js:基本のキホン
アクションゲームの基礎部分だけを抜き出したサンプルがありますので,まず,それから見ていきます。
enchant(); //おまじない
window.onload = function() {
//ページが開いたら以下の処理を実行
var game = new Game(320, 320);
//Gameオブジェクトを320×320で生成
game.preload('bear.gif');
//画像のロード指定
game.onload = function() {
//Gameオブジェクトができたら以下を起動
var bear = new Sprite(20, 30);
//20×30のスプライトを生成
bear.image = game.assets['bear.gif'];
//スプライトに画像を割り当て
bear.addEventListener('enterframe', function() {
//ここがイベントリスナ部分
this.x += 3;
//スプライトのx座標に3を足す
});
game.rootScene.addChild(bear);
//スプライトをシーンに登録
};
game.start(); //ゲーム開始
};
非常にシンプルですね。プログラムの大まかな流れは,
オブジェクト生成
イベントリスナ登録(メイン処理部分)
オブジェクトをシーンに登録
実行
のようになります。これはenchant.jsのゲームすべてに共通する流れです。
基本的に,各種処理の起動はイベントドリブンですので,プレイヤーのキー入力など,さまざまなイベントに対して対応する処理を書いていきます。それぞれのオブジェクトでどのイベントでどのような反応をするかを示した「イベントリスナ」を登録していくことでゲーム処理を記述するのが原則となります(リストの太字部分)。オブジェクト指向というと,クラスを作ってメソッドで処理を記述する形が多いかと思いますが,enchant.jsではインスタンスごとにイベントリスナで処理を指定するという流れのようです。
イベントドリブンですので,非同期処理が基本のようですが,上記のようにフレーム開始イベントに同期した処理も書けます。ゲームでは同期処理のほうが多くなるでしょう。標準状態のenchant.jsでは,1/15秒ごとにフレーム開始イベントが発生します。
さて,サンプルをこのまま実行すると,熊が走り去ってしまいますので,まずは右端で折り返すようにしてみましょう。
イベントリスナの前に以下のようなbearのメンバ変数を追加します。
bear.dir=1;
bear.spd=3;
続いてイベントリスナ内を書き換えます。
if(this.x > game.width || this.x < 0) bear.dir *=-1;
this.x += bear.dir*bear.spd;
これで折り返すようになりました。だいたいお分かりと思いますが,移動速度を変えたいときには,spdの部分を変更してください。
イベントリスナ内で変数を定義することもできますが,それだとイベントが呼ばれるたびに初期化されるため,オブジェクトに紐づくデータは,オブジェクト定義時にメンバ変数として用意しておきましょう。
サンプル1:熊が折り返します
ダウンロード●キー操作で動かしてみる
次に,キー操作で動かしてみましょう。体裁としては,キー入力イベントのイベントリスナで処理するのが筋なような気もしますが,標準のサンプルではフレームごとの処理内で入力処理もやっていますので,ここでもイベントドリブンにこだわらずにやってみましょう。
まず,enchant.jsでのキー入力についてまとめます。enchant.jsはスマートフォンなどを主な対象としていますが,PCでのキー入力にも対応しています。ドキュメントには明記されておりませんが,キーの押下状態はシステム変数のように読み出すことができます。
上下左右の方向キー入力は,それぞれ以下のようなinputのメンバ変数に格納されています。
game.input.up
game.input.down
game.input.left
game.input.right
押されているとTrue(1)が返り,押されていないときはFalse(0)です。
また,ボタンについても3つ分が確保されています。ここでは,z/x/cの各キーをAボタン/Bボタン/Cボタンとして定義しておきましょう。Webブラウザによって多少違いがあるようですが,少なくともWindowsだと,以下のキーバインドでほぼ問題なく動くようです。
game.keybind(90, 'a'); //z
game.keybind(88, 'b'); //x
game.keybind(67, 'c'); //c
Gameオブジェクトの生成時に以上のものを加えておき,読み出しするときは,
game.input.a
game.input.b
game.input.c
の各変数を参照してください。
ということで,上記の情報を念頭にキー操作可能なように変更していきます。先ほどのスクリプトでイベントリスナ内を,
if(game.input.left) bear.x -= bear.spd;
if(game.input.right) bear.x += bear.spd;
if(game.input.up) bear.y -= bear.spd;
if(game.input.down) bear.y += bear.spd;
のように置き換えるとできあがりです。
サンプル2:方向キーで熊が動きます(PC専用)
ダウンロード●アニメーションさせてみる
スプライトのアニメーションは,Spriteオブジェクトのframe変数を変更することで実現できます。bear.gifの場合,60×30ドットの画像ですが,スプライトの大きさは20×30ドットで指定されており,実はこのスプライトの大きさの絵が,左から順に0(中央),1(右足前),2番(左足前)のframeに自動的に格納されていますので,それを呼び出してやります。今回はなにも考えず,フレームごとに,
0→1→0→2→0 ……
という繰り返しで再生してみます。上記の繰り返しバターンを得るにはどういう方法を取ってもよいのですが,ここでは,
bear.n++;
bear.frame=((bear.n %=4)<2) ? bear.n :(bear.n!=2)*2;
のようにしています。4で割った余りを取って,2より小さいときはそのまま,2だったら0,そうでないなら2を返す処理です。最終的に同じ動作であれば,if文で書くなり,テーブル参照にするなり,三角関数を使うなりしてください。もっと単純に,0のパターンを途中に追加して順に読み出せばいいような画像にする手もありますので,好みの処理で実装してかまいません。とにかく,frameの部分を書き換えると表示されるパターンが変わるということを理解しておいてください。
これを実行すると……ウエイトを入れてないので,歩いているというより走っているようにしか見えませんけど,ちゃんと動いて見えますのでこれはこれでよしとしましょう。
サンプル3:熊をアニメーションさせます
ダウンロードenchant.jsで使うオブジェクト
enchant.jsでは,なにができるのかをもう少し見ていきましょう。
まず,ゲームで使えるオブジェクトについて。
Game
ゲーム全体を表すオブジェクトです。プレイヤーの入力などは,このオブジェクトが扱います。Label
文字表示用のオブジェクトです。HTMLタグが使用できます。Sprite
スプライト表示用のオブジェクトです。Map
BG表示用のオブジェクトです。スプライトチップを並べて表現するもので,衝突判定も同時に指定します。Scene
画面を切り替えるためのオブジェクトです。なにを表示するかを管理し,スプライトなどはこのSceneオブジェクトに登録することで表示されるようになります。ほかにもありますが,主なものは以上です。
これらは,
- enchant.EventTarget
-- enchant.Node
--- enchant.Entity
---- enchant.Sprite
---- enchant.Label
---- enchant.Map
といった階層構造になっており,Spriteは,上位のクラスが持つ要素を基本的に受け継いでいます。ドキュメントを読む際に少し意識しておくとよいでしょう。
そのほか,注意点と個人的な不明点など気が付いたことをまとめておきます。
●画像のロード
「preload」とありますが,実質的に「load」だと思っておいてください。先読みしなくても実行時に読まれるといったことはありません。ゲームのonloadの前に実行されるものですので,ゲーム処理中に記述することはできません。また,1行で書かないといけませんので,スクリプトの先頭部で,ゲーム内で使用する画像名をカンマで区切ってずらずらと書いていってください。
こうしてpreloadされた画像は,game.assetに記録されます。
●ウィンドウのサイズ
Gameオブジェクトの生成時に大きさを指定しますが,これは表示される大きさではありません。表示部分はWebブラウザの表示領域に応じて自動的に調整されます。プログラム内で扱われる各種座標値は,Gameオブジェクトで指定した値や,画像サイズなどのピクセル数そのものをベースに計算されます。
●画像にマージンを
おそらく,ウィンドウサイズに従って画像を自動拡大している関係だと思われるのですが,アニメーションパターンを表示すると,隣のパターンが縦横1ピクセルのラインで滲み出して,ゴミのようにちらつくことがあります。サイズいっぱいで描かれたパターンだと防ぎようがないのですが,新しくパターンを作る際はできるだけ1ライン分の空き枠を取るようにしたほうが安心です。
●関数のスコープ
プログラムを作るうえで,決まった処理は関数化するのはよくあることですが,普通に記述された関数は,Webブラウザであるwindowの管理下の関数となります(らしい)。私の理解不足もあるのですが,イベントリスナ内など,enchant.jsとの値のやり取り手段をきちんと把握しておりません。すみません。たぶんクロージャって奴を使うんですかね……。
●キーワード
標準のサンプルでは,ドキュメントには明記されていないキーワードが使われているのですが,すでに説明しているもの以外で,例えば,
bear.addEventListener('enterframe', function() {
は,
bear.addEventListener(enchant.Event.ENTER_FRAME, function() {
と同じ意味を持ちます。ソースを読まずに済ませたい場合は,ちょっと長くなりますが,下の形式で記述したほうがいいかもしれません。
スクロールする背景:マップ機能を使ってみよう
とはいえ,ソースを見て手作業でマップデータを作ることに絶望している人も多いのではないでしょうか。
データ自体は,ただの数値型2次元配列ないし3次元配列のように見えます。n×mのマップであれば(n×m×2)のデータを渡してやればよさそうです。雰囲気としては,最初の配列がチップ番号の並び,次の配列が重ね合わせオブジェクトの配置でしょうか。それがマルチレイヤーになっているようです。プログラムを見ると背景を重ねて作ったstageというグループオブジェクトのxとyを変更してスクロールさせています。
マップ内で通れるところと通れないところの判定は,座標を指定してhitTestメソッドに渡してやればよいようで,扱い自体はさほど難しそうではありません。
……マップ作成以外の部分は,ですが。
ということで,今回は,サンプルマップを流用しつつということで少しだけいじってみました。本格的な使い方をするには不十分ですが,同水準のものはちょっと作れないのでしかたありません。
さて,サンプルプログラムを見ていると基本的な使い方が分かります。先ほど,マップのレイヤーがグループ化されていると述べましたが,さらにプレイヤーキャラクターもそのマップにグループ化されているのが分かります。キャラクターオブジェクトのx,y座標が,Gameオブジェクト内のローカル座標ではなく,マップオブジェクト全体に対するローカル座標値になっていることに注目しましょう。
とはいえ,結論からいえば,調整しきれておりません。今回は少しいじったサンプルを提示するに留めておきます。
内容は,キャラをいわゆるVX系のものに差し替えて,マップをトーラススクロールに対応させたものです。
現在のRPGサンプルはマップ内を端から端まで歩くタイプですが,上に抜けると下から出る感じで上下左右ががつながった構造のマップとしています。理屈は簡単で,マップを縦横2倍に継ぎ足して,端に近づいたら,データがつながっている端の部分まで移動させているだけです。
サンプル4:RPG風サンプル(トーラススクロール版)
ダウンロードちなみに,今回使用したキャラデータは,「First Seed Maerial」さんからお借りしました。いろいろなゲームで使える(ここ重要)フリー素材を提供されており,マップ用のデータも多く配布されているので,enchant.jsとは相性がよさそうなサイトです。
なお,注意点ですが,キャラは1キャラずつファイルを分割してください。次に,歩きパターンで少し手を抜くので,3パターンのデータのうち,真ん中の列を右端に追加して,4パターンの画像を登録してください。imageの登録では,drawなどを使わず,普通にファイル名を指定してassetsから読み出してください。
First Seed Material
http://www.tekepon.net/fsm/JavaScript開発の流れ:開発者ツールを使ってみよう
ブラウザとテキストエディタだけでゲームを作れるとはいうものの,いざやってみるとJavaScriptプログラムのデバッグは大変です。最近ではたいていのWebブラウザに開発者ツールが標準装備されるようになっていますので,ぜひ利用したいものです。
IE9の場合,F12キーを押すと開発者ツールが起動します。デバッグしたいページを開いた状態でF12を押してください。開発者ツールが起動した時点で,F5キーで再読み込みをしてやれば,(問題が発生している場合)エラーメッセージなどを表示してくれます。
以下にごく簡単な使い方を示しておきますので,この手のツールを使ったことがない人は参考にしてください。IE9以外のブラウザでもだいたい似たような手順となります。
ブレイクポイントを何か所にも埋め込んでおいて,「続行」ボタンで少しずつ進めながら変数の状態を見ることもできます。スクリプトの編集がその場でできないのが多少不便ですが,使うと使わないのとでは効率がまったく違いますので,ぜひ活用しましょう。
なお,「デバッグ開始」をした場合は,ちゃんと「デバッグ終了」ボタンを押さないとWebブラウザが反応しなくなるので注意してください。
こういったツールを使うのと並行して,私は画面にデバッグ用のラベルをいくつか埋め込んでおいて,実行中の変数値を表示するといった方法を取っています。
サンプルシューティングゲーム
そのサンプルゲームも,吉里吉里用に作成したスプライトライブラリのデモという位置付けのものでしたので,表示周りをenchant.jsのものに置き換えています。こういった「移植」であることから,enchant.js用のサンプルとして見ていただくのはちょっとどうかと思う点も多い実装になっていますが,ある程度ちゃんとしたゲームが動くという部分だけ確認してみてください。
サンプル6:シューティングゲーム(PC用)
ダウンロードHTML5とJavaScriptでこれくらいのことはできるようになったのです。
さて,吉里吉里もイベントドリブンベースのシステムなのですが,以前Synthe用に制作した吉里吉里のスプライトライブラリでは,イベントドリブンだと処理が書きにくいのでフレームごとに呼ばれるメインループを作りました。ところが,enchant.jsでは,オブジェクトごとにフレーム開始のイベントも備えられているので,わざわざタイマーでイベントを起こしてやらなくてもよくなっています。しかし,それぞれのオブジェクトごとにフレーム開始イベントがあるのも煩雑です。
どれくらいイベントにこだわっているシステムなのかと一瞬悩みましたが。オブジェクト(スプライト)の衝突でイベントが発生したりということもないようですし,前述のようにキー入力などは,キー入力イベントでイベントハンドラを書くだけでなく,システム変数としても用意されています(私も吉里吉里のライブラリではそうしてました)。
イベントごとに処理を書いていくほうが綺麗だという人もいるのでしょうが,無理にイベントドリブンにこだわることもないような気がしてきました。
ということで,イベントリスナ部分では,メインになるオブジェクトについて,フレーム開始イベントを取り,そこからメインループ関数を呼んでいます。メインループ関数では,該当オブジェクト以外も含めたゲーム処理を実行します。これで個人的な好みでいえば,非常にすっきりした形になりました。
グローバル変数化
眉をひそめる方が続出な気配がありますが,上記のようにそのまま処理を持ってきた関係で,今回のプログラムではほとんどの変数をグローバル変数にしています。イベントリスナに処理を記述する際に,そこにゲーム処理を全部入れるというのがあまり気が進まなかったのと,もともとのプログラムが処理を関数に分けていたのですが,そのままではうまく呼び出せなかったので,スパッといろんなものをグローバル化しました。TJS版からの変更点
もともとTJSはJavaScriptと似た言語ですので,変更部分は非常に少なくて済みました。主な変更点と注意点は,変数の実体をちゃんと作っておかないと使えない場合が多いこと,整数除算がないので一部処理を変更せざるをえなかったこと,整数へのキャストがないので(整数自体がないのですが),同様に一部処理の変更が必要だったことなどです。スプライトライブラリの仕様はかなり違いますが,結局やっていることはそう変わりませんので,呼び出し方を全部変えるだけで済みました。元に比べてプログラムが長くなっているのは,主に初期化が必要なものが多くなったことに関係しています。「KAG」(Kirikiri Adventure Game)を使わず,吉里吉里だけでゲームを作っている人というのはあまり多くなさそうですが,とりあえず参考までに。
enchant.jsの変更
本筋からは外れますが,PC用のブラウザでenchant.jsを使ったページを開くと,スクロールバーが出てしまい,カーソルキーの操作と同期して全体がスクロールしてしまうことがあります。Webブラウザウィンドウをちょっと小さめにしてF5で再表示したのちに大きさを戻すなどすれば大丈夫なのですが,ちょっと煩雑です。そこで,enchant.jsの画面サイズ設定部を書き換えて画面よりクライアント領域を少し小さめにしています。ブラウザごとに調整値は変わってきそうですが,ここではとりあえず,縦横20ピクセル小さめに設定するようにしてあります。その結果,ゲーム画面自体が右と下が20ドットほど削られたようで,ゲームにも多少影響が出ますが,とくに対処はしておりません。
画面サイズの小さなスマートフォンにとってはあまりよくないのかもしれませんが,今回のサンプルで使用しているenchant.jsは,多少いじってありますのでご了承を。
音を鳴らそう
残念ながら,enchant.jsではサウンド機能がサポートされておりません。ちょっと調べれば分かるのですが,HTML5にはAudioオブジェクトがサポートされています。もう少し調べれば分かるのですが,ブラウザごとの互換性は高くありません。
ここではブラウザの種類を調べてサポートされているフォーマットのデータを渡して……といった煩雑な処理は書きたくありませんので,今回は,鳴ったらラッキー程度の気持ちで対応するに留めておきます。HTML5対応ブラウザ自体が発展途上であり,あちこちの検証サイトの内容も食い違っていたり,日々状況は変わっています。今後のサポートの充実に期待しておきましょう。
今回用意する音声データは,WAV形式とMP3形式の2種類です。前述のように,スプリプトで選択といったことはしません。HTMLタグで埋め込み,そのタグがハンドルしているデータを再生することにします。
まず,HTML部分です。これまで,
<body>
</body>
と非常にシンプルだったBODY部にタグを入れます。今回使う音声データは2種類です。
<body>
<audio autobuffer id="sd1">
<source src="bb1.mp3">
<source src="bb1.wav">
</audio>
<audio autobuffer id="sd2">
<source src="s1.mp3">
<source src="s1.wav">
</audio>
</body>
このようにそれぞれに2種類フォーマットで用意したデータのソースを併記しておけば,かなりの確率でどっちかを拾ってくれます。あとは,運を天に任せましょう。最近のバージョンであれば,おそらく,Chrome,IE9,SafariはMP3,FirefoxはWAVファイルを読むかと思われます。
HTMLタグを使わず,JavaScriptだけでも,
sd1= new Audio('s1.mp3');
のように指定することでサウンドデータを利用できますが,ブラウザによって再生できるデータを自動選択して読んでくるようなことはありません。やるとなると,ブラウザを判別して適したデータ一つ選んで渡すという処理になりますが,対応状況は日々変わっており,対応していたはずのものが使えなくなっていることもあったりします。また,判別していないブラウザでは音が鳴らなくなります。タグでのデータ併記であれば,新しいブラウザが出てきてもそのまま対応できますし,仕様変更でも柔軟に対応できます。
続いてJavaScript部です。片方だけ示しますが,内容は同じです。単純に再生するだけなら,
sd1= document.getElementById("sd1"); // サウンド指定部
sd1.play(); //再生部
で大丈夫です。
ただし,ゲームの効果音の場合,サウンドバッファが一つでは連続して音が鳴ったときに途切れたり,新しい音が出なかったりします。そこで,複数のバッファを用意して,順番に使ってやるようにします。こうすることで,効果音が重なって再生され,音の途切れや不自然な挙動がなくなります。
これにはサウンドバッファを複数取ることが必要になわけですが,今回の実装では,サウンドオブジェクトの実体はブラウザ側にあるので,idを変えた<audio>タグを複数個併記しておく必要があります。ここでは2種類の音声に対して,5個ずつ並べておいたとしましょう。
では,JavaScript部です。
s1=0; //インデックス保存用変数
sd1= new Array(); //サウンド指定部
sd1[0]=document.getElementById("sd1a");
sd1[1]=document.getElementById("sd1b");
sd1[2]=document.getElementById("sd1c");
sd1[3]=document.getElementById("sd1d");
sd1[4]=document.getElementById("sd1e");
s1++;sd1[s1 %=4].play(); //再生部
このような感じで一つ使ったら次へと順に使い回していきます。ラウンドロビンという奴ですね。
この指定では,前回の音が鳴り終わってなかった場合には発音されませんが,
s1++;sd1[s1 %=4].stop();sd1[s1 %=4].play(); //強制再生
のように,強制的に新しい音を出すことも可能です。
ゲーム部分の解説
もののついでということで,Synthe版の発表時に割愛していたゲーム自体の解説も少ししておきましょう。ゲームの内容は,見てお分かりのとおり,縦スクロール(しないけど)シューティングゲームです。ゲームの仕様としては,縦シューの本質的なところだけ残してあとは削ったようなものになっています。
自機が動けるのは左右だけです。前後に動かせるようにしてもよかったのですが,左右だけでもほとんどゲーム性は変わらないのでシンプルにいきました。2行くらい加えれば前後にも移動できますので,もの足りない方はご自由に変更してください。
敵は1種類で,上から下にまっすぐ降りてくるだけです。左右に動かなくても十分だと思いますが,動かしたい方は適当に処理を加えてください。
敵の弾は自機を狙ってくるタイプです。自機を見ずにばらまくタイプは,あまり面白みがなく,弾幕系の八方に広がるような弾は9割無駄で負荷が高いだけなので割愛しました。やろうと思えば,誘導弾とかレーザーなどを入れることも可能ですが,自機を狙う弾だけあれば最低限シューティングゲームとして成り立つと思っています。
仕様面は削減していますが,ゲーム要素としては,自機/敵機のアニメーション,爆発アニメーション,効果音処理など,マップスクロールやボム以外,縦シューを作るうえでの基本要素はほとんどを入れてあるかと思います。
ゲーム自体はご覧のとおり,非常に単純な構成ですが,だんだん難度が上がっていきますので,それなりに楽しめるのではないかと思います。このゲームの難度調整では,
敵機数,敵弾数,敵弾の速度
の三つの要素を変化させています。プレイしてみれば,難度が単純に上がるのではなく,それぞれ変動しているが分かると思いますが,それぞれの要素をそれぞれ別の周期で変動させています。弾速だけ速いけど,弾数は少ないとか,「弾数は多いけど弾速はゆっくり」といった局面もあれば,たまには「敵も多くて弾も多くてしかも速い」という局面も出てくるわけです。しばらく猛攻をしのいでいれば必ず一息つけますので,追い詰められないように迎撃してください。
これらの制御には,MMORPGでいうところのHate(ヘイト)値と似た考え方を適用しています。変数名でいうとagg,つまり敵のAggro値です。これは,敵を倒すと上がり,弾を撃っても上がります。つまり,やっていれば自然にどんんどん上がっていきます。敵機数,敵弾数は仕様上の上限がありますが,弾の速度には,とくに上限を設けておりません。なお,弾が速くなるというのは,「速くなる可能性がある」というだけで,速度を底上げしているわけではありません。どちらかというと遅い弾のほうが厄介ですので,それはしっかり残してあります。
スマートフォンに対応させてみよう
現状のスマートフォン版では,
また,スマートフォンではキー入力ができませんので,バーチャルパッドに対応させる必要があります。バーチャルバッドは用意されているということだったのですが,用意されていた ui.enchant.js が動いているようには見えませんでしたので,自前で適当にボタンを作っています。同時に,画面を指が隠すため,操作と視認性の問題から,自機の位置を少し上に上げて対応しています。
(※追記:バーチャルパッドは,指を置きっぱなしにして,ぐりぐりしてやらないとうまく動かないもののようです)
タッチパッドの入力は,イベントで確認可能ですので,メインループ呼び出しだけをしていたイベントリスナ部分に,ようやく仕事らしいことをしてもらいましょう。
左ボタン画像をl_b,右ボタン画像をr_bというオブジェクトにして画面に配置します。左ボタンを例にすると,
l_b.addEventListener(enchant.Event.TOUCH_START, function(e) {touch_L=1;});
のようにして,始まった時点で,左ボタンが押された状態かどうかを保存する変数 touch_Lに1を入れます。これもグローバル変数ですので,ゲーム内のどこからでも参照できます。タッチが終わった時点で,変数の内容も変更します。
l_b.addEventListener(enchant.Event.TOUCH_END, function(e) {touch_L=0;});
これで,タッチパッド対応が完了しました。PCの場合,マウスでクリックしても動作しますので確認してみてください。
サンプル7:スマートフォン版
ダウンロード※自機やボタンが画面内に表示されないときは,ページをリロードしてください
PCでは余力がありすぎたため,もともとのプログラムではそれほど細かい最適化はされていません。今回実装はしていませんが,処理が重い部分についての改善策はいろいろ考えられます。数が多く現れる敵機や敵弾で当たり判定を取るのは,y座標が一番下あたりのときだけで十分ですし,敵機が自機を狙う部分では三角関数を呼び出していますが,自機は左右方向にしか動かず,自機も敵機もかなり粗い離散的な座標しか取りませんので,あらかじめ3次元配列にテーブル化しておくのも有効でしょう。
PC版と比べるとスペックダウンさせざるをえない部分はあったものの,とりあえず,この程度のものは動くというのは分かりました。iPhone,Android 2.1以降で動作するはずですので,スマートフォンをお持ちの方は確認してみてください。作るのがアクションゲームでなければかなり余裕を持って処理できるかもしれません。
いずれにしても,これからスマートフォンの性能はどんどん上がっていくと予想されますので,今後にいっそうの期待というところでしょうか。
- この記事のURL: