サンプルプログラム7の改造

プログラマーからひとこと

いよいよサンプルプログラム7ともこれでおわかれです。

時間をかけてサンプルがどう動いているのか見てきただけあって、今回はけっこうカンタンに話が終わるような気がします。
それだけみなさんもスキルアップしたということです。おめでとう!

前回いきなりサンプル7と関係ないビット演算の話が出てきておどろいたかもしれませんが、ちゃんと今回の話に使いますよ。
それもこれもふくめて、これまでの講座の総まとめです。
泣けるBGMなどをかけながら読んでみてください。

ゲームオーバーを作ってみよう

インテリ
さて、サンプルプログラム7のつくり方はだいたい分かったけれど……

ワンパク
イヨイヨ、このロクでもねえプログラムをマシにカイゾウするってワケだな!

博士
ソコまで言わんでもよかろうに……

神崎
いちどロードしなおしておこうか。
LOAD”SAMPLE7”
どこから手をつけたらいいのかな?

ワンパク
マッサキにおかしいトコロと言ったら、ゲームオーバーにならねェとこだろうな。

インテリ
セイカクには、ゲームオーバーになるのは「敵が自機のいる21行目まで下りてきた時」ということになるかな。

ワンパク
チッ、コマカいやつだぜ!

博士
どういうプログラムにするか、前もってハッキリとイメージしておくのはダイジじゃぞい。
まあ、思いつきでドンドン打ち込むのもひとつのダイゴミではあるが。

神崎
こまかく考えていくと、先頭の1匹が21行目についたタイミングがいいのかな。20行目のはじっこだとまだ早いって気がするし、何匹も21行目に乗っていると遅いかんじだもんね。

博士
うむうむ、そういうコトじゃ。こういうのを「仕様しようを決める」と言うのじゃが、できるだけミノガシの少ない仕様を決められるのが良いプログラマーのジョウケンじゃぞい。

ワンパク
ムムム……アトは……そうだな、画面に「GAME OVERゲームオーバー」って書かねェとな! そしてENDだ!

神崎
そうか、それはたしかにダイジだね。ちゃんとゲームオーバーだってわからないと。

インテリ
まずは、そういう仕様で作ってみようか。まずサイショにすべきコトは……

ワンパク
もともとムダだった、自機のノコり表示をヤメようぜ! コメントアウトしとくか。
0028#. ’LOCATE 0,23
0027#. ’PRINT”Г:”;LEFT;

博士
そのトオリじゃが、あいかわらずコトバがキビしいのう……。

神崎
ジッサイに敵が下におりる時のプログラムは……まずは@DWルーチンかな。
0120#. @DW
0121#. EY(I)=EY(I)+1
0122#. IF EY(I)>20 THEN EY(I)=3
0123#. ED(I)=(ED(I)+1) AND 3
0124#. GOTO @EPUT

インテリ
122行目では敵が画面の下から上にワープするように作ってあるけど、今回の改造ではココはいらないね。
0122#. ’IF EY(I)>20 THEN EY(I)=3
とりあえずコメントアウトしよう。

ワンパク
いや、せっかくIF EY(I)>20 THENなら、ソコでゲームオーバーにすりゃイイんじゃねェの?

インテリ
オシイけど、ココではまだ敵が21行目に表示されていないんだ。さっき決めた仕様どおりに作るならハズレだね。

ワンパク
チッ、コマカいハナシはニガテだぜ! ウゴいた敵を書いてるのは、そのアトの@EPUTルーチンだったか。
0137#. @EPUT
0138#. LOCATE EX(I),EY(I)
0139#. PRINT ”Е”
0140#. RETURN
どう見ても、139行目のアトにIF文を1行書けばイイはずだぜ!
0140#. IF EY(I)>20 THEN @GOVER
たいしてやるコトもなさそうだが、イチオウ新しくゲームオーバーGame OVERサブルーチンに飛ばしといたぜ。

神崎
あとはムズカシイことは何もなさそうだね。
0142#. @GOVER
0143#. LOCATE 8,11
0144#. PRINT ”G A M E  O V E R”
0145#. END

画面
博士
ウム。キチンとできておる。

ワンパク
しかし、やってみるとジミな気もするな。ドウセならこのぐらいは……
0142#. @GOVER
0143#. LOCATE PX,PY
0144#. COLOR 7
0145#. PRINT ”┷”
0146#. LOCATE 8,11
0147#. COLOR 13
0148#. PRINT ”G A M E  O V E R”
0149#. END

画面
博士
うむうむ。いくら仕様を前もって決めていても、作ってみるともっとやりたいコトは出てくるモノじゃ。ためらわずアラタに作りはじめるココロもダイジじゃぞ。

神崎
言ってるコトがバラバラな気もするけど……

博士
あと、ジブンでワケがワカらなくなる前に、ホドホドで止めておくキモチもやっぱりダイジじゃな。

ワンパク
どうしろってんだ!

インテリ
どの考え方も同じくらい大切なものさ。うまくバランスをとってプログラムしていきたいね。

ハカセ 画面リセット

このコラムもこれがサイゴかもしれんと思うと……ワシじゃ、コラムのヌシことハカセじゃ。
さっきのプログラムではCOLOR15にモドさないウチにENDしておるから、その先にナニを打っても赤い字になるのう。COLOR命令を何度も使うプログラムじゃと、いつもCOLOR 15で終われるとはかぎらん。そこで、ベンリな裏ワザを教えておくぞい。
“Rボタン + 左ボタン + STARTボタン”
こうDSiのボタンを押せば、画面がリセットされるのじゃ。
イマのところCOLOR 15:CLSと打つのとそう変わらんのでアリガタミがウスいかもしれんが、グラフィックやBG・スプライトに手を出すといよいよベンリになるコマンドじゃぞ。

スピードを変えてみよう

インテリ
次はどこを改造するのがいいかな。ゲームとしてちゃんとしてないのは……

ワンパク
そりゃ、敵のスピードが早すぎるコトだな! ゲームオーバーを作ってマスマスよくワカッたが、敵をオソくしねえとハナシにならねェぜ!

神崎
そう言えば、スピードをコントロールしてる部分がもうあったような……

ワンパク
! タシカに、オレとしたコトがワスレてたぜ!
0035#. @LOOP
0036#.  GOSUB @MYSHIP
0037#.  GOSUB @MYSHOT
0038#.  GOSUB @ALIEN
0039#.  GOSUB @SCORE
0040#.  VSYNC(1)
0041#. GOTO @LOOP
メインループの中のVSYNC(1)で1/60秒オソくしてたんだったな。じゃあ、コレをもっとオソくすりゃイイんじゃねェか?
0040#.  VSYNC(20)

神崎
あれ? なんだか……

RUN
神崎
……あ、そうか。

ワンパク
し、シマッタ! 自機がオソいのは100歩ゆずっても、ショットがオソいのだけはガマンならねー!
というかコレ、ただゲームのテンポがユルくなったダケだな!

インテリ
そういうコトだね。VSYNC()はその場でポーズするようなモノだから、ゲーム全体のスピードが変わってしまうんだ。

神崎
VSYNC()じゃなくて、敵だけが遅くなるような改造にしないとダメなんだね。

ワンパク
ムムム……自分やショットはウゴくが、敵はウゴかない……ん? そう考えるとアンガイよくあるパターンじゃねえか?

インテリ
そう、敵を動かす部分をスキップすればいいってコトだね。
0117#. @EMOVE
0118#. IF ??? THEN @EPUT
0119#. ON ED(I) GOTO @RI,@DW,@LF,@DW
118行目を書きたして、ある条件のトキ以外は敵の場所を変えないことにしたよ。

神崎
ずっとスキップしっぱなしじゃ動かなくなっちゃうから、このIF文で「何回かに1回だけ動く」ようにすればいいってことか……。

ワンパク
だいたいハナシが見えてきたゼ。こうすりゃイイんだな!
0085#. ’--- シンリャクシャ
0086#. @ALIEN
0087#. ESTOP=ESTOP+1
まず敵をウゴかすオオモトのブブンに、変数ESTOPをヨウイするぜ! コイツは敵を止めるSTOPためのフラグだな。
0088#. IF ESTOP==9 THEN ESTOP=0
こうやって、10回に1回はにモドるようにしておくゼ! アトは、スキップするジョウケンを……
0119#. @EMOVE
0120#. IF ESTOP THEN @EPUT
IF ESTOP THEN、ツマリESTOPがゼロじゃなければスキップする、ってコトにすればデキアガリじゃねえか!?

インテリ
おっ、やったじゃないか! これで敵のスピードだけが10分の1になったね。

ワンパク
ワレながら、ジョウタツぶりがミゴトだぜ……。

神崎
あれ? そういえばこの10回に1回はにもどるってパターンは……

博士
どうやらオボエていたようじゃのう。ワンパク君のプログラムの、ドコを変えればいいかワカッたかの?

ワンパク
オレのプログラムのシュウセイがゼンテイかよ!

神崎
この88行目はやっぱりけずって……
0087#. ESTOP=ESTOP+1
0088#. IF ESTOP==9 THEN ESTOP=0

ワンパク
そしたら、数がフエるイッポウじゃねェか?

神崎
うーん、タシカにそうなんだけど。
0119#. IF FLOOR(ESTOP%9) THEN @EPUT
スキップの条件をこう書きかえれば、10回に1回だけFLOOR(ESTOP%9)の答が0になる……つまりスキップしないってコトになるよね。

インテリ
I=I+1でループするとき、FLOOR(I%N)と書くとが『の倍数』になるたびゼロまでおり返しながら1増えていく」。前におぼえたホウソクだね。

博士
やってるコトは同じじゃが、IF文がひとつ消えてコンピューターにやさしく、短いプログラムになったのう。
ESTOPの数はサイゴまで増えっぱなしじゃが、このゲームではメモリーのゲンカイまで増えるマエにゲームオーバーになるから、ソレもよかろう。

ワンパク
そこまでコウリツをモトめるその考えカタ、オレは気にくわねェな!

博士
タシカに、ワンパク君のプログラムの方が初心者にはわかりやすいとも言えるわい。
どこまでプログラムにコウリツを求めるのがイイのか、それはプログラマーにとってエイエンのテーマじゃ。

インテリ
どれがセイカイとも言えない、ってコトかな。ちなみにスキップする回数はちょっと変わるけど、こういう方法もあるよ。
0087#. ESTOP=(ESTOP+1) AND 7
#####.  :
0119#. IF ESTOP THEN @EPUT
ビット演算のくわしいセツメイはもうはぶくけど、9回に1回だけESTOPがゼロになってスキップしなくなるプログラムだね。
コンピューター的にはわり算よりビット演算の方が早いから、ボクはコレがFLOOR()を使うよりもスキかなあ。

ワンパク
ケッキョク、プログラムするヤツのスキズキってコトか……。

博士
セイカイがひとつとかぎらんのも、プログラムのおもしろさじゃな。プログラマー2人に合作させるとおたがいのビガクがぶつかって、見ていてオモシロいもんじゃよ。

神崎
……やじうま?


クリア画面をつくってみよう

ワンパク
スピードが変わって、だいぶゲームらしくなってきたな!

インテリ
敵が少なくなると、デタラメに撃っても当たらなくなるのがよくわかるね。だけどあんまりじっくり当てようとしていると、敵にせめこまれてゲームオーバーになっちゃう。ゲームにはこういうカケヒキがないとね。

博士
なんだかハジメてホメられた気がするわい……。

神崎
こうなってくると、敵を全滅させた時に何もないのがさびしいね。ゲームクリア画面を作っておこうよ。

ワンパク
そうムズカシくないんじゃねェか? とりあえず敵の数をチェックするための変数がいるな。
0012#. ELEFT=EMAX
敵の最大数を決める変数EMAXがもともとあったから、新しいEnemy残りLEFT変数ELEFTに使うことにするゼ!

インテリ
敵が1匹やられるたびに、変数ELEFTを1へらせばいいね。
0110#. ELEFT=ELEFT-1
あとはこの数がゼロになったら、ゲームエンドGame ENDでいいかな。
0111#. IF ELEFT==FALSE THEN @GEND

神崎
そこからは新しいサブルーチンになるね。
0157#. @GEND
0158#. LOCATE 11,11
0159#. PRINT ”シンリャク ミスイ”
0160#. END
こんなところかな?

画面
博士
サスガにサクサクいくようになったのう。
クリアしたシュンカン、はじめてゲームタイトルが出てそのイミがアキラカになる。ワシのノゾミどおりの、ハリウッド的クールなエンシュツじゃ。

神崎
そこまで考えてなかったけど……。

インテリ
あっと、まだオワリじゃないよ。ひとつワスれてることがあったね。

ワンパク
そうか? トクにおかしいトコロはなさそうだが……

SCORE: 190
神崎
あっ! 最後の敵を撃った点が入ってないよ!

インテリ
最後の敵が撃たれたらスグに@GENDに飛んでいるから、こうなっちゃうね。

ワンパク
じゃあ、@GENDに飛んだサキですぐに点を入れればイイんじゃねェか?
0157#. @GEND
0158#. GOSUB @SCORE

インテリ
ず……ずいぶんストレートな方法でカイケツしてきたね。

博士
@SCOREに行って10点プラスして帰ってくるワケじゃな。10点以上の敵を倒してクリアしたトキはどうする、というモンダイはあるが……そもそも10点以上の敵がいないので、マチガイなくこれでカイケツはしておるな。

神崎
いいの? ハカセにしてはアッサリしてるけど。

博士
何点の敵がアイテでもOKなプログラムを組むのがリソウではあるんじゃが……、ショクンならフラグをうまく使えばスグにできるじゃろうしな。10点以上の敵を出すヨテイもないイマは、これでよかろう。

ワンパク
(さっき点の入れワスれに気がつかなかったコトを、ゴマカそうとしてるんじゃねェか……?)


ショットをボタン操作に変えてみよう

インテリ
あとは、ショットを画面タッチからAボタンに切り替えれば、ボクらのキボウもだいたいかなったことになるかな。

神崎
ショットは70行目で入力チェックしていたんだっけ。
0070#. IF TCHST==FALSE THEN @MSSKIP
システム変数TCHSTFALSEだったら(タッチされてなかったら)ショットをスキップする、っていうやり方だね。

ワンパク
そのままBUTTON()に置きかえればすむコトじゃねェか! ……ン?
この前にB=BUTTON()してるから、IF B AND 16と書けばAボタンを押してるのはワカるが……

インテリ
そのままそう書くと、THENの後のイミがちがっちゃうね。
スキップするのは変えたくないから、ここには「IF (Aボタンが押されていない) THEN @MSSKIP」と書きたいけど……。

神崎
えーと、ビット演算のときにおぼえたけど、BUTTON()で変数に入る数は、2進数に直すと第0ビットから1ケタずつ、スイッチになってるんだったよね。
十字ボタン↑1000001
十字ボタン↓2000010
十字ボタン←4000100
十字ボタン→8001000
Aボタン16010000
Bボタン32100000
 :   :

インテリ
たとえば「十字ボタン→」と「Aボタン」が同時押しされていれば、変数に入る数は2進数では011000になるね。
これにAND 16すると……
    011000
AND 010000
  = 010000

Aボタンの第4ビットだけが立っているかどうかわかる、というのがおさらいになるね。

ワンパク
オサライかよ、オレのキライなナガレだぜ!

神崎
うーん……そして、Aボタンが押されていない時にAND 16すると……
    001000
AND 010000
  = 000000

ほかのボタンを押していても、答はゼロになるわけだね。あたりまえだけど……

ワンパク
オ、オイ! ソレじゃねえか!?

神崎
え?

博士
! (……ワンパク君! キミが……)

ワンパク
AND 16すりゃ、Aボタンを押してないトキにはゼッタイになるんだろ?
イマまで使ったことのねェやり方だけどよォ、それなら「IF (Aボタンが押されていない) THEN @MSSKIP」ってのも書けそうじゃねェか!
0070#. IF B AND 16==FALSE THEN @MSSKIP
……ム。ヘンな書き方になった気もするが……

RUN
ワンパク
チクショウ! 合ってると思ったんだが……ウマく動いてねえ!

インテリ
いやいや、考え方はバッチリだよ。

ワンパク
ナニ?

インテリ
その書き方だと、「B=TRUEAND16==FALSE」のように読めちゃうから、おかしくなるんだね。カッコでかこんで、こうして書けばいいんだよ。
0070#. IF (B AND 16)==FALSE THEN @MSSKIP

神崎
ホントだ! これならうまく動くよ!

博士
ワンパク君……イージーミスでつまずいたものの、あれだけニガテだったビット演算の考え方をキチンとリカイしたようじゃのう。ワシはうれしいぞい。

ワンパク
ダテにあのメンドクセェ講座をくぐり抜けてきたワケじゃねえぜ!


まとめのようなもの

インテリ
おぼえたコトは、なんでもムダにはならないってコトだね。
ビット演算にかぎらず、このBASIC講座で勉強したことは、イガイなところで役に立ったり、応用しだいでもっとイロイロな使いみちがあるハズさ。

博士
そういうコトじゃな。読者のショクンも、このサンプルをさらに改造するコトから始めてみてはどうかな?
これまでの講座でおぼえた命令を組み合わせると、イガイにやりたいコトができたりするものじゃ。

神崎
たしかに、まだ改造したいポイントはいっぱいあるね。敵の種類をふやしてみたいし、プレイヤーが1機でおわりじゃなくてもいいよね。

博士
もっとカラフルにするのもよさそうじゃな。敵がやられたトキにバクハツパターンを出すなどもいいじゃろう。
こういう見た目のエンシュツはイガイに考えるトコロが多く、うまくいったトキのジュウジツ感も大きいのでオススメじゃぞ。

インテリ
やりたいコトに手が届かない時は、説明書をながめてみるのもいいかもね。
ムズカシそうだけど、ここまで読んだ今なら、何が書いてあるのかカナリわかるようになってるハズだよ。

ワンパク
……テメーら! サイゴだけマジメなコトでまとめて、さもキョウイク的なナイヨウだったってカオしてんじゃねえぞ!


今回のまとめ

画面リセット
“Rボタン + 左ボタン + STARTボタン”を押せば、画面がリセットされます。
まとめ方
最後のほうで、みんないい子になって教育的なことでまとめれば、まるでいい講座だったように思い込めるものです。