【13:アクションゲーム】enchant.jsを使ったアクションゲーム
プロジェクトNo.13:アクションゲーム
前回に引き続き、enchant.jsというHTML5とJavaScriptベースのゲームエンジンで簡単なゲームを作ってみました。
ゲームの仕様は、
画面に表示されている敵を全部倒せばクリアです。
スマホからは画面の十字キーをタップで方向転換。右下部分をタップすると攻撃です。
PCからは画面をクリックするか、キーボードの矢印キーとzボタンがそれぞれに対応しています。
なんかすごくシンプルなゲームですけど、前回とは違う機能をたくさん使ったので、ご紹介させてもらいます。
マップの作成
背景を画像に設定することもできるけど、RPGのような1マス1マスのマップデータを配置する方法もあります。
enchant.jsが用意しているMapクラスを使っていきます。
オブジェクトの作成と画像データの読み込み
前回、Spriteの説明をしましたがそれと同じで画像を読み込んで、画像の中のどの部分を使うかを指定します。
マップは2次元配列で場所とデータを指定し、レイヤのように重ねることも可能です。(-1はnullデータとなります)
JavaScript
// 背景 var baseMap = new Map(16, 16); baseMap.image = game.assets['./img/map1.png']; // マップを2レイヤ重ねる baseMap.loadData([ [ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1], [ -1, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, -1], [ -1, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, -1], [ -1, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, -1], [ -1, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, -1], [ -1, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, -1], [ -1, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, -1], [ -1, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, -1], [ -1, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, -1], [ -1, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, -1], [ -1, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, -1], [ -1, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, -1], [ -1, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, -1], [ -1, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, -1], [ -1, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, -1], [ -1, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, -1], [ -1, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, -1], [ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1] ],[ [ 7, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 7], [ 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 7], [ 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 7], [ 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 7], [ 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 7], [ 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 7], [ 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 7], [ 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 7], [ 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 7], [ 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 7], [ 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 7], [ 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 7], [ 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 7], [ 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 7], [ 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 7], [ 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 7], [ 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 7], [ 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23] ]);
マップに障害物を配置する
マップの描画自体の指定は上記で行い、障害物判定は別にMAPオブジェクトの持つcollisionDataに指定します。
1が障害物ありという意味になります。
JavaScript
// 障害物の判定用 1:障害物有り baseMap.collisionData = [ [ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] ];
イベント
前回は毎フレームイベントと画面タッチイベントを紹介しましたが、
今回はキーボード操作のイベントを紹介します。
- aボタン押下時イベント及びaボタン離した時イベント
JavaScript
game.keybind('Z'.charCodeAt(0), 'a'); // z を a ボタンとして割り当てる // aボタン押下時イベント game.addEventListener("abuttondown", function(e) { buttonAction(); }); // aボタン離した時イベント game.addEventListener("abuttonup", function(e) { aPush = 0; });
enchant.jsではaボタンとbボタンというイベントハンドラが用意されていて、
それらをどのキーボードに対応させるのかを上記のコードで指定できます。
十字キーパッド
今回はプラグインも使ってみました。
まず、UI系のプラグインであるui.enchant.jsをHTML上で読み込みます。
HTML
<script src="./js/lib/ui.enchant.js"></script>
JavaScriptではオブジェクトを生成し、位置を指定したら、
game.input.leftなどでイベントハンドラを取得できるので、それぞれに処理を記述していくだけです。
JavaScript
// 十字キー var pad = new Pad(); pad.x = 0; pad.y = 304; // 各方向ボタンの処理 if (game.input.left) { this.direction = 1; // 移動方向の設定 0:down, 1:left, 2:right, 3:up this.vx = -4; // 移動距離の設定 } else if (game.input.right) { this.direction = 2; this.vx = 4; } else if (game.input.up) { this.direction = 3; this.vy = -4; } else if (game.input.down) { this.direction = 0; this.vy = 4; }
画面のスクロール設定
アクションゲームだと画面の端まで行く前に画面全体がスクロールします。
これはどうやって実現するかというと、
主人公キャラクターが中心からある一定の距離を移動したら、画面全体も移動させるということを行っています。
JavaScript
// 画面のスクロール設定 var stage = new Group(); stage.addChild(baseMap); stage.addChild(knight); stage.addChild(knight_hit); stage.addChild(knight_hitU); stage.addChild(knight_hitD); stage.addChild(knight_hitR); stage.addChild(knight_hitL); stage.addChild(enemies); stage.addChild(enemies_hit); // ステージに「毎フレーム実行イベント」を追加します。 stage.addEventListener('enterframe', function(e) { if (this.x > 200 - knight.x && knight.x <= 250) { this.x = 200 - knight.x; } if (this.x < 140 - knight.x && knight.x != 0) { this.x = 140 - knight.x; } if (this.y > 200 - knight.y && knight.y <= 300) { this.y = 200 - knight.y; } if (this.y < 160 - knight.y && knight.y != 0) { this.y = 160 - knight.y; } });
Groupというクラスを使って全てのオブジェクトをまとめてから、そのGroupに対して移動処理を行っています。