インベーダーの3Way弾攻撃編
『弾幕インベーダー』の解説シリーズの4回目はインベーダーの3Way弾攻撃について見ていきたい思います。インベーダーの攻撃は4種類用意しており、どの段にいるインベーダーかによってどの攻撃をするのかをあらかじめ決めています。一番下の段と、下から2段目のインベーダーが「3Way弾」で攻撃してきます。
『弾幕インベーダーゲーム』で遊びたい方は以下よりアクセスしてください。
ソースコードはGitHub上にアップしています。
3Way弾制御の定義一覧
3Way弾制御に使用するグローバル変数一覧
変数名 | 内容 |
---|---|
tama | インベーダーの各ミサイルのオブジェクトを管理する二次元配列 |
3Way弾のクラス定義(BombAクラス)
3Way弾は中央と左右の3方向に向かって飛ばしています。左右への広がりは等間隔にしており、その情報は「l」フィールドに持たせています。またそれぞれの方向毎にミサイルの画像も用意しているため、画像のパス情報も3つ持つようにしています。
フィールド名 | 型 | 場所 | 内容 |
---|---|---|---|
image1 | string | インスタンス | 真ん中のミサイルの画像のファイルパス |
image2 | string | インスタンス | 左側のミサイルの画像のファイルパス |
image3 | string | インスタンス | 右側のミサイルの画像のファイルパス |
x | number | インスタンス | 3Way弾ミサイルのX座標 |
y | number | インスタンス | 3Way弾ミサイルのY座標 |
l | number | インスタンス | 左右方向への移動量 |
3Way弾オブジェクトの初期化
3Way弾のオブジェクトの初期化はjsファイルが読み込まれた際に行っています。
for (let j = 0; j <= 30; j++) {
tama[0][j] = new BombA(false, "res/tama1a_16x12.png", "res/tama1b_16x12.png", "res/tama1c_16x12.png");
}
3Way弾の配列は0~30までの31発分のオブジェクトをあらかじめ用意しています。つまり最大同時に31発分のミサイル攻撃が可能としています。実際には攻撃はランダムな抽選を行っており、31発が同時に発射されることはほぼありません。for文の条件式の閾値(30という値)を変えることで、同時に発射できるミサイル数をコントロールすることができます。
3Way弾制御の関数一覧
3Way弾を制御を主としている関数一覧は以下となります。
クラス名 | 内容 |
---|---|
shotchance() | インベーダーの攻撃の抽選 |
tamamovea() | 3Way弾制御のメイン関数 |
respone() | 自機のリスポーン処理 |
インベーダーの攻撃の抽選処理(shotchance関数)
インベーダーの攻撃はランダムに抽選を行っています。この抽選は10msに1回、上から4段目と5段目にいるインベーダーの数だけ行われます。
shotchance()
function shotchance(_i, _j){
let ratio;
switch (_i) {
//上から5段目と4段目のインベーダーのとき
case 4:
case 3:
ratio = Math.random()*120000; //抽選
if(ratio < stage*10 + 500 - tcount*10) { //ステージ数と生き残っているインベーダーの数で抽選
for(let k = 0; k < tama[0].length; k++) { //全3Wayミサイルを走査
if(!tama[0][k].alive){ //ミサイルが未発射のとき
tama[0][k].alive = true; //ミサイルを発射状態にセット
tama[0][k].x = teki[_i][_j].x + 12 + tx; //ミサイルのx座標を対象となるインベーダーのx座標にセット
tama[0][k].y = teki[_i][_j].y + 16; //ミサイルのy座標を対象となるインベーダーのy座標にセット
tama[0][k].l = 0; //左右方向の移動量を0にセット
break;
}
}
}
break;
~中略~
}
}
攻撃の抽選はステージ数とインベーダーの生存数をパラメータとして決定しています。ステージ数が大きいほど、あるいはインベーダーの生存数が少ないほど攻撃する確率が高くなるような条件式としています。
3Way弾制御のメイン関数
3Way弾は3方向に発射されるインベーダーのミサイルです。左右の弾は中央から徐々に離れていくような軌道を取ります。3方向にミサイルを飛ばすというと、一見複雑な制御のように思えるかもしれませんが、コードを見ていただければお分かりのように、処理はすごく単純です。
tamamovea()
function tamamovea(){
for (k = 0; k < tama[0].length; k++) {
if (tama[0][k].alive) { //3Way弾が有効なとき
if(!miss && !clear){ //自機が被弾状態でない、かつクリア状態でないとき
tama[0][k].y = tama[0][k].y+1; //3Way弾のy座標を1px増やす
tama[0][k].l = tama[0][k].l+0.3; //3Way弾の左右ミサイルのx座標を0.3増やす
}
//3Way弾の描画
tamaimga = new Image();
tamaimgb = new Image();
tamaimgc = new Image();
tamaimga.src = tama[0][k].image1;
tamaimgb.src = tama[0][k].image2;
tamaimgc.src = tama[0][k].image3;
ctx.drawImage(tamaimga, tama[0][k].x, tama[0][k].y, 8, 12);
ctx.drawImage(tamaimgb, tama[0][k].x-tama[0][k].l, tama[0][k].y, 8, 6);
ctx.drawImage(tamaimgc, tama[0][k].x+tama[0][k].l, tama[0][k].y, 8, 6);
//3Way弾と自機の当たり判定
if(tama[0][k].y >= 460 && tama[0][k].y <= 474) {
if (tama[0][k].x >= x+14 && tama[0][k].x <= x+20) {
hit(); //被弾処理
} else if (tama[0][k].x-tama[0][k].l >= x+18 && tama[0][k].x-tama[0][k].l <= x+24) {
hit(); //被弾処理
} else if (tama[0][k].x+tama[0][k].l >= x+18 && tama[0][k].x+tama[0][k].l <= x+24) {
hit(); //被弾処理
}
}
//3Way弾が流れていったときの処理
if (tama[0][k].y > 500) { //3Way弾のy座標が500pxを超えたとき
tama[0][k].alive = false; //3Way弾を無効にする
}
}
}
}
ミサイルの移動
3Way弾のオブジェクトにはY座標のフィールド(y)とX軸方向に左右に移動させるためのフィールド(l)を用意しています。tamamovea()関数が呼ばれるごと(10msごと)にY座標は1ずつ増やし、左右方向のX座標は0.3ずつ増やしています。これで3つの弾が扇状に広がっていくように制御しています。
自機との当たり判定
当たり判定は3方向にミサイルが飛ぶので、それぞれの座標を使って3回分の当たり判定を行っています。
オブジェクトの処理
ミサイルは自機に当たるか、自機に当たらずそのまま流れて外へ出ていくかのどちらかですが、どちらにしてもミサイルのオブジェクトは初期化時に生成したオブジェクトを再利用しています。オブジェクトは再利用した方がいいのか、毎回作り直した方がいいのかは、ケースバイケースです。今回の3Way弾のオブジェクトの数は31個(プログラム全体のオブジェクトとしても百数十個程度)ですので、たとえ使われていないオブジェクトが存在したとしても大きな負荷にはならないという考えのもとで再利用する設計としています。
さいごに
今回はインベーダーの3Way弾ミサイルの制御についてのコードを見てきました。一般的なインベーダーゲームの攻撃は1方向しかないと思いますが、今回は3方向にミサイルが飛ぶように工夫しています。どれくらいの間隔で左右に開いていくかは実際に動かしながら調整しています。X座標方向の移動量を調整することでもっと広げて移動させることも可能です。ちょっとした工夫ですが、オリジナリティが出ていいですね。次回もインベーダーの攻撃の続きで、誘導弾について見ていく予定です。次回もお楽しみに!
ちょっと息抜き
プログラミングを学習していると、脳をフル稼働させますし、じっと座ってコーディングしているときは目も身体も疲れてしまいます。そんな時は一息入れて、Yahoo!トラベルを見て現実逃避しましょう♪
Yahoo!トラベルはお得が一杯
- 取り扱い施設数が約17000施設!
- リーズナブルな価格での宿泊施設から贅沢な宿泊施設まで掲載!
- 日程や希望の条件からプランの検索・比較が簡単!
- 期間限定のクーポンがいっぱい!
- PayPayポイントが使える・貯まる!
- エリア×テーマで最も売れている宿をデイリーで更新中!
具体的に旅行を考えている方はもちろん、旅行の計画がなくてもYahoo!トラベルを見ているだけでほんのちょっと旅行に行った気分を味わえます。良い気分転嫁が出来ると思いますので興味がある方はアクセスしてみてください。
配列tamaは各種ミサイルのオブジェクトを共通で管理する二次元配列です。3Way弾のオブジェクトは一次元配列の先頭の要素(tama[0])に格納しています。