後でフルスクリーンモードを使うことを考えて画面の大きさを640×480にしていますが、これって幅が広すぎると思いませんか? 普通縦スクロールシューティングの画面は縦長ですね。それと、敵が上端にパッと現れて、下端に達するとパッと消えますが、キャラクタの下部から徐々に現れ、消える時も徐々に消えた方がいいですね。そこで、画面の大きさは640×480のまま、真ん中の320×448の領域をゲーム画面にしたいと思います。
指定した座標がゲーム画面の外側で、キャラクタの一部分だけ画面内にある場合は、画面に現れている部分だけ描画するようにします。
1.画面の大きさを指定する |
2.描画位置が完全に画面の外側である場合、描かない |
3.一部分だけ画面内にある場合、コピー元の指定領域を調節する |
4.描画する |
「プログラム起動時の初期設定」で、ゲーム画面の幅、高さを変数xsize,ysizeに代入します。
xsize=320
ysize=448
以降のプログラムではxsize、ysizeを参照します。あちこちに、320、448と書くと、後で変えたくなった時に面倒くさいですね。こうしておけば、この部分を書き換えるだけで済みます。
2.描画位置が完全に画面の外側である場合、描かない |
指定位置に指定した絵を描く処理をサブルーチンにします。呼び出し側(メインルーチン)で、座標を変数gdx,gdyに代入します。ファイル中の、コピー元の座標をgdox,gdoyに代入します。キャラクタの幅をgdw、高さをgdhに代入します。(gdはgraphic draw、oはoriginal、wはwidth、hはheightの略です。)そしてこのサブルーチンを呼ぶと、絵が描かれるようにします。
座標は、ゲーム画面に対するものです。つまり、320×448の矩形領域の、左上端が(0,0)、右下の端が(319,447)です。
描画位置が完全に画面の外側である場合、何もしないという処理はこうなります。
if (gdx+gdw<=0)|(gdx>=xsize)|(gdy+gdh<=0)|(gdy>=ysize) { return }
図中の"="は代入の意味ではありません。
図とif文が結びつかない人は、"gdx+gdw-1<0"と"gdx+gdw<=0"は同じである点に注意して下さい。
3.一部分だけ画面内にある場合、コピー元の指定領域を調節する |
キャラクタが左側にはみ出している場合、例えば、指定したx座標が−5の時、左側の幅5ドットの部分を除いた領域をコピーして、x座標が0の位置に貼り付けます。つまり、コピー元の画像のx座標はgdox+(-gdx)です。幅はgdw-(-gdx)です。
右側にはみ出している場合、描画する座標はそのままです。コピー元の画像の幅はxsize-gdxとなります。キャラクタの右端のx座標はgdx+gdw-1、画面の右端のx座標はxsize-1ですから右側にはみ出している条件は"gdx+gdw-1>xsize-1"、つまり"gdx+gdw>xsize"です。
if gdx<0 {
gdox=gdox-gdx
gdw=gdw+gdx
gdx=0
}
else {
if gdx+gdw>xsize { gdw=xsize-gdx }
}
"else"は、「もし条件が成り立っていなかったら」です。
if 条件式 {
処理1
}
else {
処理2
}
で、「もし条件が成り立っていたら処理1を、成り立っていなければ処理2を実行せよ」という意味です。
y座標についても同じ考え方です。
上の場合、完全に画面内におさまっていたら、何もいじりません。
ddposで指定する位置は、(gdx,gdy)ではありません。ゲーム画面の左余白、上余白を考慮しなければなりません。
ddpos (640-xsize)/2+gdx,(480-ysize)/2+gdy
ddsetrect gdox,gdoy,gdw,gdh
ddgcopy 1
以上をふまえて、サブルーチンは以下のようになります。
; 指定した絵を描画
*Graphic_Draw
; 描画するキャラクタが端の方にあり、一部分だけ描画する場合も
; 表示できるようにするサブルーチン
;
; gdx,gdy : 描画する座標
; gdox,gdoy : グラフィックのコピー元座標
; gdw : 幅
; gdh : 高さ
if (gdx+gdw<=0)|(gdx>=xsize)|(gdy+gdh<=0)|(gdy>=ysize) { return }
if gdx<0 {
gdox=gdox-gdx
gdw=gdw+gdx
gdx=0
}
else {
if gdx+gdw>xsize { gdw=xsize-gdx }
}
if gdy<0 {
gdoy=gdoy-gdy
gdh=gdh+gdy
gdy=0
}
else {
if gdy+gdh>ysize { gdh=ysize-gdy }
}
ddpos (640-xsize)/2+gdx,(480-ysize)/2+gdy
ddsetrect gdox,gdoy,gdw,gdh
ddgcopy 1
return
例えば、自機を描画する、メインルーチン側の記述はこうなります。
gdx=playerx:gdy=playery
gdox=0:gdoy=0
gdw=32:gdh=32
if (rkey=1)&(lkey=0) { gdox=32 }
if (lkey=1)&(rkey=0) { gdox=64 }
gosub *Graphic_Draw
敵が徐々に現れるようにするためには、出現時のy座標を0から−32に変更するだけでよいのです。またy座標が448に達したら消すようにしていたのも、ysizeに達したら、に変えます。
[プログラム全体と絵をダウンロード]
※今回の改造が影響する箇所はすべて修正してあります。
・saveについて |
プログラムのsave(保存)は、実行する前に行った方がいいと思います。HSPの場合大抵は大丈夫だと思いますが、実行して、万が一強制終了(Ctrl+Alt+Del)によっても止められず、リセットするしかないようなバグが起こってしまった場合、saveしていなかったら悲惨ですね。昔、プログラミングはアセンブリ言語で行うのが一般的だった時代、saveもせずに実行するのは無謀以外の何物でもなかったみたいです。
|
・実行する前に読み直すべきか? |
プログラムを書いたら、即実行したいと思うのが人情です。しかし、実行する前に読み直すようにすると、バグが残る可能性がぐんと減ります。もちろん、実行させてみればすぐ見つかるようなバグの方が多いです。書いて即実行すると、バグが起こって、原因がありそうな部分だけ読み直し、修正してまた実行させてみる、というスタイルになるかと思います。この場合、ある特定の条件でしか起こらない、めったに起こらないバグが残る可能性があります。
|
[目次へ]|[前へ]|[次へ]