このページの本文へ

enchant.jsで懐かしのインベーダーゲームを作ろう (3/4)

2012年08月29日 11時00分更新

文●古籏一浩

  • この記事をはてなブックマークに追加
本文印刷

敵の攻撃

 ブロック崩しのブロックは攻撃してきませんが、インベーダータイプのゲームでは敵はビームを撃って攻撃してきます。今度は、敵がビームを発射するプログラムを作成します。

 あまり増やしてしまうと敵から集中砲火を浴びてしまい、すぐにゲームオーバーになってしまうので、敵が撃ってくるビームは最大でも8つまでとします。

// 敵のレーザービームを格納する配列(最大でも8つまで)
var enemyLaser = new Array();
var maxLaser = 8;

 敵のビームを表示できるように初期化します。この部分は以前説明したブロック崩しのブロックの追加と同じですが、異なるのはZ座標値を設定している点です。敵が撃ってくるビームは敵よりも後ろになるようにしています。4にすると前面になります。値を変更してどのようになるか見てみるのもよいでしょう。

 // ------------ 敵のレーザービームを初期化 -----------------
 function initEnemyLaser(){
 for(var i=0; i<maxLaser; i++){
  enemyLaser[i] = new Sprite(4, 16);
  enemyLaser[i].image = game.assets["images/laser.png"];
  enemyLaser[i].flag = false// レーザービームが存在するかどうかのフラグ
  enemyLaser[i].x = 0// X座標
  enemyLaser[i].y = -999// Y座標
  enemyLaser[i]._style.zIndex = 1// Z座標
  game.rootScene.addChild(enemyLaser[i]);
 }
 }

 敵のビームの移動処理は自機の場合と同じですが、複数のビームを処理する必要があります。ビームの情報は配列に入れてあるので、for()命令を使って繰り返し処理します。

 // ------------ 敵のレーザービームを移動する -----------------
 function moveEnemyLaser(){
 for(var i=0; i<maxLaser; i++){
  if (!enemyLaser[i].flag){ continue; } // レーザービームがない場合は繰り返しの先頭に
  enemyLaser[i].y= enemyLaser[i].y + 4; // Y座標の移動処理
  if (enemyLaser[i].y > game.height){  // 画面外か?
  enemyLaser[i].flag = false// 発射するレーザービームの存在をONにする
  }
 }
 }

 敵のビームの発射処理です。乱数を使って、発射する敵の配列の位置を求めています。画面上に敵が存在したらビームを発射しますが、その際すでにビームが8つ発射済みであれば何もしません。より高い頻度でビームを発射させるには、

Math.floor(Math.random() * 100);

の100の数値を小さくします。数値を大きくすると、ビームの発射頻度は低くなります。

// ------------ 敵のレーザービームを発射する -----------------
function startEnemyLaser(){
 var pointer = Math.floor(Math.random() * 100); // レーザービームを発射する敵の配列位置を求める
 if (!enemy[pointer] || enemy[pointer].y < 0 ){ return; } // 敵が存在しない場合は発射しない
 for(var i=0; i<maxLaser; i++){
 if (!enemyLaser[i].flag){ // 空いているレーザービームの配列要素があるか
  enemyLaser[i].flag = true// 発射するレーザービームの存在をONにする
  enemyLaser[i].x = enemy[pointer].x + 14// X座標を設定 
  enemyLaser[i].y = enemy[pointer].y + 16// Y座標を設定
  return// 以後の処理はしない
 }
 }
}

敵のビームと自機の接触判定

 敵が撃ってきたビームと自機の接触判定を作ります。enchant.jsではintersect()メソッドとwithin()メソッドで接触を判定できます。intersect()メソッドは矩形での判定、within()メソッドでは距離の判定です。

 今回はintersect()メソッドを使ってビームと自機を判定します。すでに自機のビームと敵の接触判定にも使っているので特別難しいことはありませんが、実際に使ってみると違和感があります。intersect()メソッドは厳格にキャラクター同士のサイズで判定しているので、見た目上は接触していないのに、接触していると判断されてしまうのです。

 このような場合、自機よりもひとまわり小さいサイズで判定すると違和感がなくなりますが、enchant.jsのintersect()メソッドには、そのような範囲を指定する機能がありません。そこで以下のように一時的にx,y,width,heightプロパティをもつオブジェクトを作成し、自機よりもひとまわり小さいサイズにしておきます。

 一時的に作成したオブジェクトと敵のビーム同士の接触を判定することで、実際にプレイしたときの違和感が少なくなります。

自機よりも1まわり小さいサイズの当たり判定にする

自機よりも1まわり小さいサイズの当たり判定にする

// ------------ ■自機と敵のレーザービームの接触判定を行う -----------------
function hitCheckLaser(){
 // 自機の判定用に仮のオブジェクトを作成しXY座標と幅を設定する
 var temp = {
 x : fighter.x+4,
 y : fighter.y+12,
 width : 24,
 height: 20
 }
 for(var i=0; i<maxLaser; i++){
 if (enemyLaser[i].intersect(temp)){  // 接触したらゲームオーバー
  game.rootScene.backgroundColor = "red"// ゲームの背景色を赤色に設定
  game.stop();
  alert("自機が破壊されました。もう駄目です。スコアは"+game.score+"点でした");
  return// 以後の処理は行わないようにする
 }
 }
}

 ここまでの処理を組み込んだものが以下のサンプル3です。

敵がビームを発射してくるようになった。ビームに当たると即ゲームオーバーになる

■サンプル3:ソースコードは省略(実際のゲームの実行ページ

この連載の記事

一覧へ
Web Professionalトップページバナー

この記事の編集者は以下の記事をオススメしています

ASCII.jp会員サービス 週刊Web Professional登録

Webディレクター江口明日香が行く