弾を撃ちながら移動するの巻


 ちょっとネタとしてやりたかったので、いきなりですが「弾を撃ちながら移動する」です。

 初心者がシューティングゲームを作ろうとすると、よくこのようなプログラムを組んでしまいがちです。

screen 0,640,480,1
A=0
B=0
X=320
Y=430

*MAIN
redraw 0
color 0,0,0
boxf 0,0,639,479
stick S,31
if S&1 : X-=16 : if X<20 : X=20
if S&4 : X+=16 : if X>611 : X=611
color 255,255,255
pos X,Y
mes "A"
A=X
B=Y
redraw 1
if S&16 : goto *TAMA ;・・・(1)
await 50
goto *MAIN

*TAMA
B-=16
color 255,255,0
pos A,B
mes "|"
await 50
if B>0 : goto *TAMA ;・・・(2)
goto *MAIN

 これを実行してみてください。カーソルキー左右で自機を移動し、スペースキーで弾が撃てます。どうでしょう、弾を撃っている間は左右に動けないはずです
 プログラミング初心者の80%はこの手のミスをおかします(マイクロソフト調べ←ウソ)。例えるなら、フランス料理店へいってフィンガーボールの水(注:指を洗うための水)を飲んでしまう人くらい多いです。

 冗談はさておき(でもよくあるミスなのは間違いないです)、上のプログラムの流れを追ってみましょう。

 ラベル*MAINでは自機の移動を行っています。「stick S,31」でキー入力の状態を取り込み、そのあとの2行で左右移動の判定、自機の表示となっています。そして(1)スペースキーが押されていた場合、ラベル*TAMAへ飛びます。弾のY座標を上へ移動させて表示したあとに、(2)画面外に出ていなければもう一度この部分を繰り返します。そう、問題はここなんですね。弾が出ている間は自機の移動に処理が回ってこないわけです。

 これを修正したのが、下のリストです。

screen 0,640,480,1
A=0
B=0
X=320
Y=430
T=0

*MAIN
redraw 0
color 0,0,0
boxf 0,0,639,479
stick S,31
if S&1 : X-=16 : if X<20 : X=20
if S&4 : X+=16 : if X>611 : X=611
color 255,255,255
pos X,Y
mes "A"
if(S&16=16)&(T=0) : T=1:A=X:B=Y ;・・・(1)
if T=1 : gosub *TAMA ;・・・(2)
redraw 1
await 50
goto *MAIN

*TAMA
B-=16
color 255,255,0
pos A,B
mes "|"
if B<0 : T=0 ;・・・(3)
return

途中までは同じなので省略します。
(1)では、スペースキーが押されたときに「弾を出した」というサインとして変数Tを1にして、変数AとBにそれぞれX,Y座標を代入します。
(2)で、変数Tが1になっている=弾が出ているときにサブルーチン*TAMAへ飛びます。
・ラベル*TAMAでは、先ほどと同じように弾の移動を行います。
・そして、(3)弾が画面から出た時点で、現在弾は出ていないということで変数Tを0に戻します。
・以上のことが終わったら、returnで元へ戻ります。

 リアルタイムゲームを作る場合、「1セットの処理で、全ての動作を行う」のが基本です。もしもプログラムを組んだのにキャラが出ない、動かないといったことがあれば、ちゃんとその部分へ処理がいっているかどうかを確かめましょう。アルゴリズムが悪い場合などももちろんありますが、このケースだとプログラムの流れを目や指で追えば簡単にわかります。次に、何か忘れていないか確かめましょう。たとえばキャラを表示させていないとか。


戻る