シューティングゲームを作ろう その5 |
9.種類0番の敵 |
敵の種類は0番から2番までの3種類あるものとします。
0番の敵は、まっすぐ降りてきて、下端まで達したら斜め上に動きます。左斜め上か、右斜め上かは、自機に近づく方向に決めます。
つまり、この敵の動きは2段階に分かれます。まっすぐ降りてくるのを第0段階、斜め上に動くのを第1段階とします。
敵の種類を配列enemy_kind、今第何段階であるかを配列enemy_phaseに入れます。
9-1.種類0番の敵の出現 |
;敵の出現 if scroll_cnt \ interval == 0 { for n, 0, ENEMAX if enemy_state(n) == 0 { _break } next if n != ENEMAX { enemy_kind(n) = rnd(3) enemy_state(n) = 1 enemy_cnt(n) = 0 switch enemy_kind(n) case 0: enemy_phase(n) = 0 enemy_x(n) = rnd(GWIDTH - 32 + 1) enemy_y(n) = -32 enemy_dx(n) = 0 enemy_dy(n) = 2 swbreak case 1: ・ ・ ・ case 2: ・ ・ ・ swend } }
scroll_cntは、メイン・ループを1周するたびに1増やすものとします。
; ;メイン・ループ ; *Main_Loop ・ ・ ・ scroll_cnt++ goto *Main_Loop
つまり、メイン・ループを1周するたびに1ドットスクロールするわけです。
intervalドットスクロールするたびに敵を出すということは、scroll_cntがintervalの倍数の時に敵を出すということです。
;敵の出現 if scroll_cnt \ interval == 0 { 敵を1匹出す処理 }
for n, 0, ENEMAX if enemy_state(n) == 0 { _break } next
敵の配列変数のうち空いている(敵の状態が「存在しない」である)要素を探します。その添え字nを取得します。
if n != ENEMAX {
nがENEMAXであるということは、すでに敵が最大数に達している(enemy_state(0) 〜 enemy_state(ENEMAX - 1)がすべて0以外)ということです。その場合は出しません。
enemy_kind(n) = rnd(3)
種類0番から2番のうちどれを出すかは、ランダムに決めます。
enemy_state(n) = 1 enemy_cnt(n) = 0
どの種類でも共通に設定する初期値です。敵の状態を「通常」にします。敵用のカウンタを0にします。
switch enemy_kind(n) case 0: enemy_phase(n) = 0 enemy_x(n) = rnd(GWIDTH - 32 + 1) enemy_y(n) = -32 enemy_dx(n) = 0 enemy_dy(n) = 2 swbreak
敵の種類別に設定する初期値です。種類0番の敵の初期値は上の通りです。
敵の段階は、最初は第0段階です。
この敵は上から現れます。x座標は0 〜 GWIDTH - 32のうちランダムに決めます(敵の大きさはすべて32×32です)。
第0段階では、真下に2ドットずつ動きます。
9-2.種類0番の敵の移動 |
;敵の移動 for i, 0, ENEMAX if enemy_state(i) == 1 { enemy_x(i) += enemy_dx(i) enemy_y(i) += enemy_dy(i) switch enemy_kind(i) case 0: switch enemy_phase(i) case 0: if enemy_y(i) == GHEIGHT - 32 { enemy_phase(i) = 1 if enemy_x(i) >= myship_x { enemy_dx(i) = -2 } else { enemy_dx(i) = 2 } enemy_dy(i) = -2 } swbreak case 1: if enemy_x(i) <= -32 | enemy_x(i) >= GWIDTH { enemy_state(i) = 0 } swbreak swend swbreak case 1: ・ ・ ・ case 2: ・ ・ ・ swend enemy_cnt(i)++ } next
for i, 0, ENEMAX if enemy_state(i) == 1 {
状態が「通常」の敵だけ移動します。存在しない敵や爆発中の敵は移動しません。
enemy_x(i) += enemy_dx(i) enemy_y(i) += enemy_dy(i)
どの種類の敵でも共通の移動処理です。本サンプルの敵の移動はシンプルで、enemy_dx(i)、enemy_dy(i)をx座標、y座標に足しこんでいくだけです。
switch enemy_kind(i) case 0: switch enemy_phase(i) case 0: if enemy_y(i) == GHEIGHT - 32 { enemy_phase(i) = 1 if enemy_x(i) >= myship_x { enemy_dx(i) = -2 } else { enemy_dx(i) = 2 } enemy_dy(i) = -2 } swbreak case 1: if enemy_x(i) <= -32 | enemy_x(i) >= GWIDTH { enemy_state(i) = 0 } swbreak swend swbreak
種類別に行う移動処理です。0番の敵については、switch 〜 swendが入れ子になっている点にご注意ください。これは、
if enemy_kind(i) == 0 { if enemy_phase(i) == 0 { ・ ・ ・ } else { if enemy_phase(i) == 1 { ・ ・ ・ } }
と同じです。
第0段階では、y座標が下端に達したら段階を1に変更します。
敵のx座標が自機のx座標以上であれば、敵は自機より右にいるものとみなし、左斜め上に動くようにenemy_dx(i)、enemy_dy(i)を変更します。そうでなければ敵は自機より左にいるものとみなし、右斜め上に動くように変更します。
第1段階では、画面左端または右端からはみ出したら消します。
enemy_cnt(i)++
どの種類の敵でも共通して行う処理です。敵用のカウンタを1増やします。つまりこれは、敵が何回動いたかを数えるカウンタです。
なお、敵の移動処理は敵の出現処理より前に書きます。