弾を撃ちながら移動するの巻
ちょっとネタとしてやりたかったので、いきなりですが「弾を撃ちながら移動する」です。
初心者がシューティングゲームを作ろうとすると、よくこのようなプログラムを組んでしまいがちです。
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セットの処理で、全ての動作を行う」のが基本です。もしもプログラムを組んだのにキャラが出ない、動かないといったことがあれば、ちゃんとその部分へ処理がいっているかどうかを確かめましょう。アルゴリズムが悪い場合などももちろんありますが、このケースだとプログラムの流れを目や指で追えば簡単にわかります。次に、何か忘れていないか確かめましょう。たとえばキャラを表示させていないとか。