敵を出し、移動します。
1.敵の配列変数を宣言する |
2.敵の移動パターンを定義する |
3.敵の変数に初期値を代入する |
4.敵を出現させる |
5.敵を移動する |
6.敵を描画する |
7.現在位置を少し進める |
敵は最大10個まで存在できることにします。自機の弾と同様、存在フラグ(enemyf)と座標(enemyx,enemyy)を配列変数として宣言します。あともう一つ、敵用のカウンター(enemycnt)を用意します。これは、敵のアニメーションと、敵の動きのために使います。
dim enemyf,10
dim enemyx,10
dim enemyy,10
dim enemycnt,10
これは、「プログラム起動時の初期設定」に入れます。
「全体の流れ」の所でちょっと、一つ一つの種類について動きをプログラミングしていく場合と、移動パターンをデータ化してしまって、処理は一つですむようにする場合がある旨を書きました。ここでは、簡単にたくさんの敵の種類を作れる、後者の方にしようと思います。
こんなふうに、左右にふらふらしながら降りてくる敵を作ります。
最初、左に8ドット、下に4ドット動かします。2回目は左に6ドット、下に4ドット動かします。3回目は左に4ドット、下に4ドットです。
何番目にx方向に何ドット、y方向に何ドット動かすかを配列変数enemvdx(enemy move dxの略)、enemvdyに代入します。
dim enemvdx,16
dim enemvdy,16
enemvdx.0=-8:enemvdy.0=4
enemvdx.1=-6:enemvdy.1=4
enemvdx.2=-4:enemvdy.2=4
enemvdx.3=-2:enemvdy.3=4
enemvdx.4=0:enemvdy.4=4
enemvdx.5=2:enemvdy.5=4
enemvdx.6=4:enemvdy.6=4
enemvdx.7=6:enemvdy.7=4
enemvdx.8=8:enemvdy.8=4
enemvdx.9=6:enemvdy.9=4
enemvdx.10=4:enemvdy.10=4
enemvdx.11=2:enemvdy.11=4
enemvdx.12=0:enemvdy.12=4
enemvdx.13=-2:enemvdy.13=4
enemvdx.14=-4:enemvdy.14=4
enemvdx.15=-6:enemvdy.15=4
これを順々に敵の座標に足しこんでいくと、ふらふらと動きます。15までいったら、0に戻って繰り返します。
これも、「プログラム起動時の初期設定」に入れます。
「ステージスタート時の初期設定」で、存在フラグに0を代入します。
repeat 10
enemyf.cnt=0
loop
まだ背景のスクロール処理を作っていないのですが、敵はスクロールに合わせて出していきたいので、自機が今ステージのマップ上のどこにいるのかを表す変数mappnt(map pointの略)を追加します。最初が0で、1ドットスクロールすると1増えることにします。
mappnt=0
ここでは、64ドットスクロールするたびに2匹ずつ敵を出します。すると、mappntが64の倍数の時に出すことになります。ある数がある数の倍数であるかどうかを調べるのに、便利な演算子があります。
if mappnt\64=0 {
敵を出す処理
}
"\"はモジュロ演算子というもので、mappntを64で割った余りを求めます。余りが0であるということは、64の倍数だということです。
敵を出す処理ですが、自機から弾を出す処理と同様、要素0から順に存在フラグを見ていき、空いている(存在フラグが0である)要素に割り当てます。1度に2匹出すので、変数nに今何匹出したかを記憶させることにします。
n=0
repeat 10
if enemyf.cnt=0 {
敵を1匹出す処理
n=n+1
if n=2 { break }
}
loop
空きが2箇所以上あれば2匹出しますし、1箇所しかなければ1匹だけ出しますし、1箇所もなければ1匹も出しません。
敵を1匹出す処理は、座標を決め、存在フラグを1にし、敵用のカウンターを0にします。
y座標は0です。x座標は、乱数で決めることにします。乱数というのは、「でたらめな値」です。サイコロをふると1から6までがでたらめに出ますが、それと同じです。
rnd 値を入れる変数,上限の値
これが、乱数を得る命令です。0から上限の値よりも1小さい数までのうちのどれかが変数に代入されます。
randomize
これは、乱数系列を変える命令です。乱数の出方を変えます。これがないと、プログラムを動かすたびに毎回同じ並びの乱数となります。サイコロを5回ふって、1,4,6,2,5という順に目が出たとすると、次にサイコロを5回ふると、また1,4,6,2,5の順に目が出てしまうということです。この命令はプログラムの最初に入れるといいですが、ここではステージスタート時に毎回乱数系列を変えることにします。
敵が左右にふらふらしていることも考慮し、画面からはみ出さないよう、32から576までの値のどれかをx座標にすることにします。ただし、2匹横に並べて出すので、下手をすると敵同士が重なってしまいます。敵の幅が32ドットなので、x座標には32の倍数しか設定しないことにすると、部分的に重なったりしません。完全に重なる危険はありますが。
rnd r,18
enemyx.cnt=(r+1)*32
1行目で、0から17のうちのどれかをでたらめに(ランダムに、という言い方をします)選んで、rに入れます。2行目で、1を足しますから1〜18となり、32倍しますから、32から576までの32の倍数となります。
しかし、やはり完全に重なるのは嫌ですね。同じ乱数が2回続けて出たら、2匹のx座標は等しくなってしまいます。そこで、前に出た乱数を変数wに記憶させておいて、それとrの値が違えばそれでよしとし、同じだったら、違う値が出るまでrnd命令をやり直すことにします。
repeat
rnd r,18
if r!w { break }
loop
w=r
wには最初に−1を入れておきます。(1回目のrnd命令で、必ず違う値になるから。)
repeatに引数を指定しないと、永久にループを繰り返します。(break文で抜け出します。)これは、
*aaa
rnd r,18
if r=w { goto *aaa }
w=r
と同じですが、ラベルを追加するのが鬱陶しければ引数のないrepeat文を使うといいです。
以上より、敵を出す処理は以下のようになります。
if mappnt\64=0 {
n=0
w=-1
repeat 10
if enemyf.cnt=0 {
repeat
rnd r,18
if r!w { break }
loop
w=r
enemyx.cnt=(r+1)*32
enemyy.cnt=0
enemyf.cnt=1
enemycnt.cnt=0
n=n+1
if n=2 { break }
}
loop
}
なお、"if r!w { break }"の方のbreak文は、あくまでも内側のrepeat〜loopから抜けるのであって、外側のrepeat〜loopからは抜け出しません。
[目次へ]|[前へ]|[次へ]