サンプルプログラム7の改造
プログラマーからひとこと
いよいよサンプルプログラム7ともこれでおわかれです。時間をかけてサンプルがどう動いているのか見てきただけあって、今回はけっこうカンタンに話が終わるような気がします。
それだけみなさんもスキルアップしたということです。おめでとう!
前回いきなりサンプル7と関係ないビット演算の話が出てきておどろいたかもしれませんが、ちゃんと今回の話に使いますよ。
それもこれもふくめて、これまでの講座の総まとめです。
泣けるBGMなどをかけながら読んでみてください。
ゲームオーバーを作ってみよう
インテリ「さて、サンプルプログラム7のつくり方はだいたい分かったけれど……」
ワンパク「イヨイヨ、このロクでもねえプログラムをマシにカイゾウするってワケだな!」
ハカセ「ソコまで言わんでもよかろうに……」
神崎「いちどロードしなおしておこうか。
LOAD”SAMPLE7”
どこから手をつけたらいいのかな?」ワンパク「マッサキにおかしいトコロと言ったら、ゲームオーバーにならねェとこだろうな。」
インテリ「セイカクには、ゲームオーバーになるのは「敵が自機のいる21行目まで下りてきた時」ということになるかな。」
ワンパク「チッ、コマカいやつだぜ!」
ハカセ「どういうプログラムにするか、前もってハッキリとイメージしておくのはダイジじゃぞい。
まあ、思いつきでドンドン打ち込むのもひとつのダイゴミではあるが。」
まあ、思いつきでドンドン打ち込むのもひとつのダイゴミではあるが。」
神崎「こまかく考えていくと、先頭の1匹が21行目についたタイミングがいいのかな。20行目のはじっこだとまだ早いって気がするし、何匹も21行目に乗っていると遅いかんじだもんね。」
ハカセ「うむうむ、そういうコトじゃ。こういうのを「仕様 を決める」と言うのじゃが、できるだけミノガシの少ない仕様を決められるのが良いプログラマーのジョウケンじゃぞい。」
ワンパク「ムムム……アトは……そうだな、画面に「GAME OVER 」って書かねェとな! そしてENDだ!」
神崎「そうか、それはたしかにダイジだね。ちゃんとゲームオーバーだってわからないと。」
インテリ「まずは、そういう仕様で作ってみようか。まずサイショにすべきコトは……」
ワンパク「もともとムダだった、自機のノコり表示をヤメようぜ! コメントアウトしとくか。
0028#. ’LOCATE 0,23
0027#. ’PRINT”Г:”;LEFT;
」0027#. ’PRINT”Г:”;LEFT;
ハカセ「そのトオリじゃが、あいかわらずコトバがキビしいのう……。」
神崎「プログラムの中で敵が21行目におりてくるとすると……@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
」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行書けばイイはずだぜ!0138#. LOCATE EX(I),EY(I)
0139#. PRINT ”Е”
0140#. RETURN
0140#. IF EY(I)>20 THEN @GOVER
たいしてやるコトもなさそうだが、イチオウ新しく」
神崎「あとはムズカシイことは何もなさそうだね。
0142#. @GOVER
0143#. LOCATE 8,11
0144#. PRINT ”G A M E O V E R”
0145#. END
」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
」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
ハカセ「うむうむ。いくら仕様を前もって決めていても、作ってみるともっとやりたいコトは出てくるモノじゃ。ためらわず新しく作りはじめる心もダイジじゃぞ。」
神崎「言ってるコトがバラバラな気もするけど……」
ハカセ「あと、自分でワケがワカらなくなる前に、ホドホドで止めておく心もやっぱりダイジじゃな。」
ワンパク「どうしろってんだ!」
インテリ「どの考え方も同じくらい大切なものさ。うまくバランスをとってプログラムしていきたいね。」
画面リセット
このコラムもこれがサイゴかもしれんと思うと……ワシじゃ、コラムのヌシことハカセじゃ。さっきのプログラムではCOLORを15にモドさないでENDしておるから、その先にナニを打っても赤い字になるのう。COLOR命令を何度も使うプログラムじゃと、いつもCOLOR 15で終われるとはかぎらん。そこで、ベンリなワザを教えておくぞい。
- “Rボタン + 左ボタン + STARTボタン”
- こうDSiのボタンを押せば、画面がリセットされるのじゃ。
ACLSと命令を打っても同じことじゃが、キーボードを使うよりラクじゃろ?
スピードを変えてみよう
インテリ「次はどこを改造するのがいいかな。ゲームとしてちゃんとしてないのは……」
ワンパク「そりゃ、敵のスピードが早すぎるコトだな! ゲームオーバーを作ってマスマスよくワカッたが、敵をオソくしねえとハナシにならねェぜ!」
神崎「そう言えば、スピードをコントロールしてる部分がもうあったような……」
ワンパク「! タシカに、オレとしたコトがワスレてたぜ!
0035#. @LOOP
0036#. GOSUB @MYSHIP
0037#. GOSUB @MYSHOT
0038#. GOSUB @ALIEN
0039#. GOSUB @SCORE
0040#. WAIT(1)
0041#. GOTO @LOOP
メインループの中のWAIT(1)で1/60秒オソくしてたんだったな。じゃあ、コレをもっとオソくすりゃイイんじゃねェか?0036#. GOSUB @MYSHIP
0037#. GOSUB @MYSHOT
0038#. GOSUB @ALIEN
0039#. GOSUB @SCORE
0040#. WAIT(1)
0041#. GOTO @LOOP
0040#. WAIT(20)
」神崎「あれ? なんだか……」
RUN
神崎「……あ、そうか。」
ワンパク「し、シマッタ! 自機がオソいのは100歩ゆずっても、ショットがオソいのだけはガマンならねー!
というかコレ、ただゲームのテンポがユルくなったダケだな!」
というかコレ、ただゲームのテンポがユルくなったダケだな!」
インテリ「そういうコトだね。WAITはその場でポーズするようなモノだから、ゲーム全体のスピードが変わってしまうんだ。」
神崎「WAITじゃなくて、敵だけが遅くなるような改造にしないとダメなんだね。」
ワンパク「ムムム……自分やショットはウゴくが、敵はウゴかない……ん? そう考えるとアンガイよくあるパターンじゃねえか?」
インテリ「そう、敵を動かす部分をスキップすればいいってコトだね。
」
0117#. @EMOVE
0118#. IF ??? THEN @EPUT
0119#. ON ED(I) GOTO @RI,@DW,@LF,@DW
ある条件のトキ以外は敵の場所を変えないことにしたよ。0118#. IF ??? THEN @EPUT
0119#. ON ED(I) GOTO @RI,@DW,@LF,@DW
」
神崎「ずっとスキップしっぱなしじゃ動かなくなっちゃうから、このIF文で「何回かに1回だけ動く」ようにすればいいってことか……。」
ワンパク「だいたいハナシが見えてきたゼ。こうすりゃイイんだな!
止める ためのフラグだな。
」
0085#. ’--- シンリャクシャ
0086#. @ALIEN
0087#. ESTOP=ESTOP+1
まず敵をウゴかすオオモトのところに、変数ESTOPをヨウイするぜ! コイツは敵を0086#. @ALIEN
0087#. ESTOP=ESTOP+1
0088#. IF ESTOP==9 THEN ESTOP=0
こうやって、10回に1回は0にモドるようにしておくゼ! アトは、スキップするジョウケンを……
0119#. @EMOVE
0120#. IF ESTOP THEN @EPUT
IF ESTOP THEN、ツマリESTOPがゼロじゃなければスキップする、ってコトにすればデキアガリじゃねえか!?0120#. IF ESTOP THEN @EPUT
」
インテリ「おっ、やったじゃないか! これで敵のスピードだけが10分の1になったね。」
ワンパク「ワレながら、ジョウタツぶりがミゴトだぜ……。」
神崎「あれ? そういえばこの10回に1回は0にもどるってパターンは……」
ハカセ「どうやらオボエていたようじゃのう。ワンパク君のプログラムの、ドコを変えればいいかわかったかの?」
ワンパク「オレのプログラムのシュウセイからのスタートかよ!」
神崎「この88行目はやっぱりけずって……
0087#. ESTOP=ESTOP+1
0088#.IF ESTOP==9 THEN ESTOP=0
」0088#.
ワンパク「そしたら、数がフエるイッポウじゃねェか?」
神崎「うーん、タシカにそうなんだけど。
」
0119#. IF ESTOP%9 THEN @EPUT
スキップの条件をこう書きかえれば、10回に1回だけFLOOR(ESTOP%9)の答が0になる……つまりスキップしないってコトになるよね。」
インテリ「「I=I+1でループするとき、I%Nと書くとIが『Nの倍数』になるたびゼロまでおり返しながら1増えていく」。前におぼえたホウソクだね。」
ハカセ「やってるコトは同じじゃが、IF文がひとつ消えてコンピューターにやさしく、短いプログラムになったのう。
ESTOPの数はサイゴまで増えっぱなしじゃが、このゲームではメモリーのゲンカイまで増える前にゲームオーバーになるから、これでもよかろう。」
ESTOPの数はサイゴまで増えっぱなしじゃが、このゲームではメモリーのゲンカイまで増える前にゲームオーバーになるから、これでもよかろう。」
ワンパク「そこまでコウリツをモトめるその考え方、オレは気にくわねェな!」
ハカセ「タシカに、ワンパク君のプログラムの方が初心者にはわかりやすいとも言えるわい。
どこまでプログラムにコウリツを求めるべきか、それはプログラマーにとってエイエンのテーマじゃ。」
どこまでプログラムにコウリツを求めるべきか、それはプログラマーにとってエイエンのテーマじゃ。」
インテリ「どれがセイカイとも言えない、ってコトかな。ちなみにスキップする回数はちょっと変わるけど、こういう方法もあるよ。
コンピューター的にはわり算よりビット演算の方が早いから、ボクはI%Nを使うよりもスキかなあ。
」
0087#. ESTOP=(ESTOP+1) AND 7
#####. :
0119#. IF ESTOP THEN @EPUT
ビット演算のくわしいセツメイはもうはぶくけど、9回に1回だけESTOPがゼロになってスキップしなくなるプログラムだね。#####. :
0119#. IF ESTOP THEN @EPUT
コンピューター的にはわり算よりビット演算の方が早いから、ボクはI%Nを使うよりもスキかなあ。
」
ワンパク「ケッキョク、プログラムするヤツのスキズキってコトか……。」
ハカセ「セイカイがひとつとかぎらんのも、プログラムのおもしろさじゃな。プログラマー2人に合作させるとおたがいのビガクがぶつかって、見ていてオモシロいもんじゃよ。」
神崎「……やじうま?」
クリア画面をつくってみよう
ワンパク「スピードが変わって、だいぶゲームらしくなってきたな!」
インテリ「敵が少なくなると、デタラメに撃っても当たらなくなるのがよくわかるね。だけどあんまりじっくり当てようとしていると、敵にせめこまれてゲームオーバーになっちゃう。ゲームにはこういうカケヒキがないとね。」
ハカセ「なんだかハジメてホメられた気がするわい……。」
神崎「こうなってくると、敵を全滅させた時に何もないのがさびしいね。ゲームクリア画面を作っておこうよ。」
ワンパク「そうムズカシくないんじゃねェか? とりあえず敵の数をチェックするための変数がいるな。
敵 の残り 変数ELEFTに使うことにするゼ!
」
0012#. ELEFT=EMAX
敵の最大数を決める変数EMAXがもともとあったから、新しい」
インテリ「敵が1匹やられるたびに、変数ELEFTを1へらせばいいね。
ゲームエンド でいいかな。
0110#. ELEFT=ELEFT-1
あとはこの数がゼロになったら、
0111#. IF ELEFT==FALSE THEN @GEND
」神崎「そこからは新しいサブルーチンになるね。
」
0157#. @GEND
0158#. LOCATE 11,11
0159#. PRINT ”シンリャク ミスイ”
0160#. END
こんなところかな?0158#. LOCATE 11,11
0159#. PRINT ”シンリャク ミスイ”
0160#. END
」
ハカセ「さすがにサクサクいくようになったのう。
クリアしたその時、はじめてゲームタイトルが出てそのイミが明らかになる。ワシのノゾミどおりの、ハリウッド的クールなエンシュツじゃ。」
クリアしたその時、はじめてゲームタイトルが出てそのイミが明らかになる。ワシのノゾミどおりの、ハリウッド的クールなエンシュツじゃ。」
神崎「そこまで考えてなかったけど……。」
インテリ「あっと、まだ終わりじゃないよ。ひとつわすれてることがあったね。」
ワンパク「そうか? トクにおかしいトコロはなさそうだが……」
SCORE: 190
神崎「あっ! 最後の敵を撃った点が入ってないよ!」
インテリ「最後の敵が撃たれたらスグに@GENDに飛んでいるから、こうなっちゃうね。」
ワンパク「じゃあ、@GENDに飛んだサキですぐに点を入れればイイんじゃねェか?
0157#. @GEND
0158#. GOSUB @SCORE
」0158#. GOSUB @SCORE
インテリ「ず……ずいぶんストレートな方法でカイケツしてきたね。」
ハカセ「@SCOREに行って10点プラスして帰ってくるワケじゃな。10点以上の敵を倒してクリアしたトキはどうする、というモンダイはあるが……そもそも10点以上の敵がいないので、マチガイなくこれでカイケツはしておるな。」
神崎「いいの? ハカセにしてはアッサリしてるけど。」
ハカセ「何点の敵を打ってもOKなプログラムを組むのがリソウではあるんじゃが……、ショクンならフラグをうまく使えばスグにできるじゃろうしな。10点以上の敵を出すヨテイもない今は、これでよかろう。」
ワンパク「(さっき自分も気がつかなかったコトを、ゴマカそうとしてるんじゃねェか……?)」
ショットをボタン操作に変えてみよう
インテリ「あとは、ショットを画面タッチからAボタンに切り替えれば、ボクらのキボウもだいたいかなったことになるかな。」
神崎「ショットは70行目で入力チェックしていたんだっけ。
」
0070#. IF TCHST==FALSE THEN @MSSKIP
システム変数TCHSTがFALSEだったら(タッチされてなかったら)ショットをスキップする、っていうやり方だね。」
ワンパク「そのままBUTTON()に置きかえればすむコトじゃねェか! ……ン?
この前にB=BUTTON()してるから、IF B AND 16と書けばAボタンを押してるのはワカるが……」
この前にB=BUTTON()してるから、IF B AND 16と書けばAボタンを押してるのはワカるが……」
インテリ「そのままそう書くと、THENの後のイミがちがっちゃうね。
スキップするのは変えたくないから、ここには「IF (Aボタンが押されていない) THEN @MSSKIP」と書きたいけど……。」
スキップするのは変えたくないから、ここには「IF (Aボタンが押されていない) THEN @MSSKIP」と書きたいけど……。」
神崎「えーと、ビット演算のときにおぼえたけど、BUTTON()で変数に入る数は、2進数に直すと第0ビットから1ケタずつ、スイッチになってるんだったよね。
」
十字ボタン↑ | 1 | 000001 |
---|---|---|
十字ボタン↓ | 2 | 000010 |
十字ボタン← | 4 | 000100 |
十字ボタン→ | 8 | 001000 |
Aボタン | 16 | 010000 |
Bボタン | 32 | 100000 |
: | : | : |
インテリ「たとえば「十字ボタン→」と「Aボタン」が同時押しされていれば、変数に入る数は2進数では011000になるね。
これにAND 16すると……
Aボタンの第4ビットだけが立っているかどうかわかる、というのがおさらいになるね。
」
これにAND 16すると……
011000
AND 010000
= 010000
AND 010000
= 010000
Aボタンの第4ビットだけが立っているかどうかわかる、というのがおさらいになるね。
」
ワンパク「オサライかよ、オレのキライなナガレだぜ……。」
神崎「うーん……そして、Aボタンが押されていない時にAND 16すると……
ほかのボタンを押していても、答はゼロになるわけだね。あたりまえだけど……
」
001000
AND 010000
= 000000
AND 010000
= 000000
ほかのボタンを押していても、答はゼロになるわけだね。あたりまえだけど……
」
ワンパク「オ、オイ! ソレじゃねえか!?」
神崎「え?」
ハカセ「! (……ワンパク君! 気づいたようじゃな……!)」
ワンパク「AND 16すりゃ、Aボタンを押してないトキにはゼッタイ0になるんだろ?
イマまで使ったことのねェやり方だけどよォ、それなら「IF (Aボタンが押されていない) THEN @MSSKIP」ってのも書けそうじゃねェか!
」
イマまで使ったことのねェやり方だけどよォ、それなら「IF (Aボタンが押されていない) THEN @MSSKIP」ってのも書けそうじゃねェか!
0070#. IF B AND 16==FALSE THEN @MSSKIP
……ム。ヘンな書き方になった気もするが……」
RUN
ワンパク「チクショウ! 合ってると思ったんだが……ウマく動いてねえ!」
インテリ「いやいや、考え方はバッチリだよ。」
ワンパク「ナニ?」
インテリ「その書き方だと、「B=TRUE」AND「16==FALSE」のように読めちゃうから、おかしくなるんだね。カッコでかこんで、こうして書けばいいんだよ。
0070#. IF (B AND 16)==FALSE THEN @MSSKIP
」神崎「ホントだ! これならうまく動くよ!」
ハカセ「ワンパク君……イージーミスでつまずいたものの、あれだけニガテだったビット演算の考え方をキチンとリカイしたようじゃのう。ワシはうれしいぞい。」
ワンパク「ダテにあのメンドクセェ講座をくぐり抜けてきたワケじゃねえぜ!」
まとめのようなもの
インテリ「おぼえたコトは、なんでもムダにはならないってコトだね。
ビット演算にかぎらず、このBASIC講座で勉強したことは、イガイなところで役に立ったり、応用しだいでもっとイロイロな使いみちがあるハズさ。」
ビット演算にかぎらず、このBASIC講座で勉強したことは、イガイなところで役に立ったり、応用しだいでもっとイロイロな使いみちがあるハズさ。」
ハカセ「そういうコトじゃな。読者のショクンも、このサンプルをさらに改造するコトから始めてみてはどうかな?
これまでの講座でおぼえた命令を組み合わせると、イガイにやりたいコトができたりするものじゃ。」
これまでの講座でおぼえた命令を組み合わせると、イガイにやりたいコトができたりするものじゃ。」
神崎「たしかに、まだ改造したいポイントはいっぱいあるね。敵の種類をふやしてみたいし、プレイヤーが1機でおわりじゃなくてもいいよね。」
ハカセ「もっとカラフルにするのもよさそうじゃな。敵がやられた時にバクハツパターンを出すなどもいいじゃろう。
こういう見た目のエンシュツはイガイに考えるところが多く、うまくいった時のジュウジツ感も大きいのでおすすめじゃぞ。」
こういう見た目のエンシュツはイガイに考えるところが多く、うまくいった時のジュウジツ感も大きいのでおすすめじゃぞ。」
インテリ「やりたいコトに手が届かない時は、説明書をながめてみるのもいいかもね。
ムズカシそうだけど、ここまで読んだ今なら、何が書いてあるのかカナリわかるようになってるハズだよ。」
ムズカシそうだけど、ここまで読んだ今なら、何が書いてあるのかカナリわかるようになってるハズだよ。」
ワンパク「……テメーら! 最後だけマジメな話でまとめて、さもキョウイク的な講座だったってカオしてんじゃねえぞ!」
- 画面リセット
- “Rボタン + 左ボタン + STARTボタン”を押せば、画面がリセットされます。
- まとめ方
- 最後のほうで、みんないい子になって教育的なことでまとめれば、まるでいい講座だったように思い込めるものです。