サンプルプログラム7 (その4)
ついにサンプルプログラムを見ていく旅もここで終わりです。
RPGなら光とか青空とか出てくるムービーが始まるころですが、まだ今回もサンプルプログラムがゲームとして完成してはいないので、青空がふいにくもって真のラスボスが出てくる場面と言ったほうがいいでしょうか。
そこはどうだっていいですね。
今回はゲーム用語のいわゆる「当たり判定」から始まります。
思えばゲームっぽい話がたくさん出てくるサンプルプログラムでした。
あなたのプログラムのウデもかなり上がったんじゃないでしょうか。
これが終わったら、自分でカンタンなゲームを作ってみるのもいいかもしれません。
いまのは死亡フラグみたいなセリフでしたが、フラグのことも学んだあなたなら、このていどのフラグはFALSEにできるはずです。

変数EMAXを敵の数に使うようになってるんだね。

敵の数をいつ変えたくなってもいいワケじゃな。前にもちらっと話したが、変数にできるトコロは変数にしておくのはダイジな心くばりじゃ。

まだデキてねェところは……ショットが敵に当たったトキ、か。

プログラムでショットが敵に当たるというのは、どういうコトかを考えるとわかるんじゃないかな?

うーん、ショットの場所と、敵の場所が重なったとき……かな?

ショットの場所は変数
MXと
MYだったよな……。敵の場所は
EX(I)と
EY(I)だから……。つまり、こんなカンジか!?
0080#. IF MX==EX(I) AND MY==EY(I) THEN GOSUB @EOUT
配列変数
(I)をツカッてるから、敵をウゴかすFOR~NEXTの中に入れないとイケねェな。
CHKCHR()命令
ワシじゃワシじゃ、今回はやたら顔を出すハカセじゃ。
ここでは話のナガレ的に出てこなかったが、当たり判定にベンリな
CHKCHR()という命令があるのを知っておったかな?
このサンプルにはカンケイない話じゃが、カンタンにセツメイしておくぞい。
- CHKCHR()命令
- たとえばA=CHKCHR(0,0)と書くと、そのトキ画面の(0,0)のバショにナニが表示されているか変数Aに入るのじゃ。
(0,0)というのはLOCATE命令で使うのと同じヨコ方向とタテ方向の数じゃな。
- 文字コード
- A=CHKCHR(0,0)と書いたトキに変数Aに入るのは、「ASCII文字コード」という数字じゃ。ナンのことかワカらんじゃろうが、ココの数字を見てくれい。
もし今回のサンプルのように、ショットの場所(MX,MY)に敵「Е(文字コード006)」がいるかどうかチェックしたければ、IF CHKCHR(MX,MY)==006 THEN~とやればいいワケじゃな。

ここまではいい調子じゃないか。敵にショットが当たったコトが分かったら、次は敵がやられるルーチン@EOUTだね。

このサンプルだと、ショットが当たった敵はすぐに消えるから、敵を空白スペースで上書きすればいいのかな。
0108#. @EOUT
0109#. LOCATE EX(I),EY(I):PRINT” ”
0110#. RETURN

タシカにそうだが……ちょっと待てよ。コレだと、次に敵のターンがきたトタンに、消えた敵もまた出てきちまうぜ!

そうか、敵を動かすためにいつも書きなおしていたんだっけ。
いちどショットが当たった敵はPRINTしちゃダメってことだなあ。

これも、いままでの応用でなんとかなるんじゃないかな?

そうか! フラグを使うんだな!

敵1匹ずつに割りあたってるフラグっていうと、
ED(I)だね。
ED(I)=0 | 右に動く | X=31になるまでX+1 | @RI |
ED(I)=1 | 下におりる | 1回だけY+1 | @DW |
ED(I)=2 | 左に動く | X=0になるまでX-1 | @LF |
ED(I)=3 | 下におりる | 1回だけY+1 | @DW |
---|

消えたっていうトクベツなフラグだから、数字には
-1をあてはめようか。
110行に追加しておこう。
0108#. @EOUT
0109#. LOCATE EX(I),EY(I):PRINT” ”
0110#. ED(I)=-1
0111#. RETURN

これでフラグは立ったから、次は敵の表示のトキにそのフラグを調べるのが……えーと、ドコがいいんだ?

Еを書いて消すなら、FORループの中ならどこでもいいとも言えるけど。でもどうせなら、もう表示しないってくらいがいいだろうね。

じゃあ、最初の方だね。
0072#. FOR I=0 TO EMAX-1
0073#. IF ED(I)==-1 THEN @PASS
#####.
0081#. @PASS
0082#. NEXT
0083#. RETURN
これで
ED(I)フラグが
-1のときは表示もされずに、次の敵まで飛ばされるよ!

ン……? ハハァ、そういうコトか!
こうすると敵が減るほどごっそりスキップする行が多くなるから、自動的にスピードが早くなる……敵をタオせばタオすほど、ゲームがムズカシくなるってワケだな!

ウムウム。どうやらショクンも、プログラムがダイブ身についてきたようじゃな。

負ける気がしねェゼ!

じゃが、せっかくならココで、よりコウリツのいいプログラムにチャレンジしてみんかな?

コウリツときやがったか。プログラムがウゴけばそれでいいんじゃねェの?

ム……ム。そういう考えもたしかにアリじゃが。
ひとつにはプログラムの動作スピードが早くなるテクニックなので、オボエておけばアトアト「重い」プログラムを動かすのに助かる、というコトはあるぞい。

アクションゲームにある「処理落ち」とか、そういうやつ?

まあそんなトコロじゃな。もうひとつのメリットとしては、プログラムが見やすくなるコトもある、とも言えるのう。

「見やすくなるコトもある」……?

逆に見にくくなるコトも、ときにはあるかも……

えー……

ま、まァまァ! じゃからこそ、シンプルプログラムのイマのうちにオボエておこうという話じゃよ。なに、たいしてムズカしいコトではないぞい。

ハカセが言いたいのは、たぶんこの部分ですね。
0080#. IF MX==EX(I) AND MY==EY(I) THEN GOSUB @EOUT

さすがはインテリ君じゃな。さよう、ソコは「敵がやられたとハッキリ決まったら、やられルーチンに行って帰ってくる。それ以外は普通に進む」となっておる。

それでフツウじゃねえか?

しかし、こうすればどうじゃ。
0080#. IF MX!=EX(I) THEN @PASS
0081#. IF MY!=EY(I) THEN @PASS
0082#. ’--- シホ゛ウ
0083#. LOCATE EX(I),EY(I):PRINT” ”
0084#. ED(I)=-1
0085#. @PASS
0086#. NEXT

ン? ……ンンン? 83~84行目は、さっき作ったやられたトキのプログラムだよな。
80行目でMX!=EX(I)ってコトは、ショットのヨコ位置と敵のヨコ位置がチガうってコトだろ。トウゼン当たってないから、@PASSに飛ぶよな。

81行目のMY!=EY(I)もタテ位置になっただけで、同じことだね。
そのどっちでもないって時は、かならずショットが当たっているって言えるから、そのままやられたことになる……

さよう。もともとのMX==EX(I) AND MY==EY(I)という条件式は、ハッキリしとるがそれだけチェックに時間がかかるものじゃ。
新しいプログラムじゃと、カンタンな理由さえあればザクザク切っているのがワカるじゃろう。

やってるコトも、GOTOで飛ぶだけだしね。
それに、まだ敵のやられチェックをカンタンにする方法は残っているよ。

ツマリ今は「敵がゼッタイにやられてない」条件をサガせばいいってコトか? ……やられてない……やられるのはショットが当たったトキ……よし! ゼンゼンわからねえ!

なにが「よし」なのか分からないけど、たぶん「ショットが画面に出ていない間は、敵はやられない」と言えるんじゃないかな。

ソコだね! ショットは変数
MSTで表示フラグをカンリしていたから……あとはカンタンだよね。
0080#. IF MST==FALSE THEN @PASS

ナルホドな。ハナシをききながらだと、ワカりやすいぜ。……ギャクに言えば、コレいきなり見たら、どういうイミなのかワカりづらくねェか?
スナオにIF MX==EX(I) AND MY==EY(I)って書いてあった方がカンタンじゃねえの?

ぜんぶヒテイされてもうたが……そのキモチも、ワカらんでもないわい。スピードを気にせんでいい初心者のコロなら、ムリしてまでやるコトではないのはタシカじゃ。

でも、人のプログラムリストを見るときに「どうしてこんな書き方を?」ってギモンはなくなるんじゃないかな。こういうプログラムの書き方があると知っておくのはムダじゃないよ。

ナイスフォローじゃ、インテリ君!
プログラムの書き方にはヒトそれぞれイロイロなポリシーがあるものじゃが、そういう考えカタを知っておくのもひとつのベンキョウじゃぞ。

ベンキョウってヒビキは気にくわねェが……ツギからこういうスキップのしかたを見てもナットクできるのはタシカか。

あれ? このプログラムRUNしてみると、ときどきショット1発で何匹も倒せることがあるよ。

ホントだな。こりゃアレだぜ、パワーアップとかによくある「カンツウダン」の動きになってるな!

「貫通弾」だね。シューティングゲームだと、敵に当たったらそこでショットは消える方がオーソドックスかな? このゲームならそうしないとカンタンすぎるしね。

ええと、敵に当たったらすぐにショットを消すわけだ。
さっきもやったけどショットの表示フラグは変数
MSTだったね。
0083#. ’--- シホ゛ウ
0084#. LOCATE EX(I),EY(I):PRINT” ”
0085#. ED(I)=-1
0086#. MST=FALSE

MST=FALSEの1行ふやしただけか。イガイにアッサリいくんだな。

フラグはうまく使うと、いろいろラクになるものさ。

あとは、敵を倒したらスコアも上げないとね。

コレはそうムズカしくなさそうな気がするぜ。
とりあえず、サイショに画面の上の方に出しておくんだろ?
0026#. LOCATE 0,0
0027#. PRINT”SCORE: ”;SC
変数
SCをスコアってことにしておいたぜ。

そして、敵がやられた時に10点プラスすれば完成かな。
0085#. ’--- シホ゛ウ
0086#. SC=SC+10
0087#. LOCATE 7,0:PRINT SC

うむ、それで合っておる。合っておるのじゃが……。

ナンだ? RUNしても、ナニもモンダイはなさそうだぜ?

しかし、ワシとしてはこういうプログラムをテイアンしたい!
0085#. ’--- シホ゛ウ
0086#. SV=SV+10
#####.
0110#. @SCORE
0111#. IF SV==0 THEN RETURN
0112#. SC=SC+10
0113#. SV=SV-10
0114#. LOCATE 7,0:PRINT SC
0115#. RETURN
メインループから
@SCOREに
GOSUBすると考えてくれい。

どういうこった? 敵がやられたトキは、ただ変数SVに10点プラスして終わりかよ?

そのあとで、変数SCを変えてPRINTするのはサブルーチン@SCOREでやるんだね。そこで変数SVもー10して、またゼロに戻る……

イミがワカらねェな! プログラムが長くなっただけじゃねえか!

先に言っちゃうと、これはLOADしたサンプルプログラムだとこうなってるんですよね。

さよう。なぜワシがこんな一見ムダに見えるプログラムにしたのか、ソコがワカるかの?

ムググ……サイゴになってイガイなナゾトキだぜ……。どう見てもムダにしか見えねェが……。

いやジッサイ、このプログラムのままじゃと、ホントにムダなのじゃ。

バカにしてんのか!

このサンプルプログラムはユーザーのショクンの手でカンセイさせるためのモノじゃからのう。そこでイミが出てくるように作ってあるのじゃよ。

うーん。そうは言っても、どういう時にヤクに立つのか……

こういう何のためにあるのか分からないプログラムは、関係のありそうな数をデタラメでも変えてみると、あんがい目に見えて分かるコトもあるよ。

というと、たとえば敵がやられたトキのSV=SV+10をSV=SV+1に変えてみる、とかいうコトか?
ヤミクモにRUNしてやろうじゃねェか!

画面の前のみんなもジッサイに変えてためしてみよう!

ウ、ウォオ!? 敵を1回撃ったら、スコアが上がりツヅケて止まらねー!

そうか……考えてみればこうなるのはトウゼンではあるよね。

アァ? ブツブツ……SVが1になってそのアト10引いてまたモドッて0じゃねェからまた10……フムフム。そりゃスコアがいつまでも上がりっぱなしにもなるな!

みんなもプログラムの流れを読むと、何が起きたのかだいたいわかるよね!

わざとデタラメにやっておるのじゃから、おかしな動きになるのはトウゼンじゃな。
しかし、このスコアを見てナニかに気付いたのではないかの?

いや、ベツに……

ココまでのナガレがダイナシになるのう……

あっ! スコアが10点ずつアニメーションで増えるように見えるよ!

そりゃタシカにそう見えるけどよォ……。メインループを1回通るたびに10点増やしてんだからトウゼンじゃ……ハッ!?

いいトコロに気付いたね。ギャクに言えば、メインループを1回通るたびに点を増やすようにすると、アニメーションで点数が増えて見えるワケだ。

ナゾがとけてきたゼ……こうすりゃハッキリするな。さっきSV=SV+1にしたトコロをSV=SV+100にしてRUNだ!

うむ! 止まった画面ではよくワカらんが、ミゴトに1匹倒すごとに100点が入り、それが10点ずつアニメーションしておる。

サブルーチン@SCOREを通るたびに、変数SVがカラになるまで10点ずつ増えてるからな! コレはメインループの中でナンドも通ることにイミがあったってワケだ!

モトモトは、たとえば1匹だけ高得点の敵を作ったらボーナス感が出るように、と作ったブブンだったんじゃが、コレももちろんセイカイじゃぞい。

まさかサイゴにこんなクイズがノコッてたとはな……。

プログラムをヒトに渡す時は分かりにくい処理にはコメントを付けておくのがキホンだけど、初心者向けのカダイとしては、まあ良かったんじゃないかな。

ケッキョクそういうアツカイなのかのう……?
- 当たり判定
- いちばんオーソドックスな当たり判定は、ぶつけるモノの位置とぶつかられるモノの位置を比べることです。ヨコ座標とタテ座標が一致すれば、それは当たっているということになります。
- CHKCHR()命令
- (変数)=CHKCHR(横座標,縦座標)
画面の指定した座標に、何のキャラクターが表示されているかが、ASCII文字コードで変数に入ります。