サンプルプログラム7 (その1)
プログラマーからひとこと
いよいよサンプルプログラム7、この講座ではこれが最後のサンプルです。サンプルプログラム5や6はやってませんけど……。
うーん、エピソード1〜3を飛ばしてエピソード4からストーリーが始まる的な?
いや、そういうものでもないですね。
サンプル5と6は、「グラフィック面」や「BG面」といった、これまでとはだいぶ違うものの話になるので、この講座ではいったんおいておきます。
新しくおぼえる命令がドーンと出てくるので、そういうのって思わずくじけちゃいそうじゃないですか。
それよりは先にスパッとアクションゲームを作ってしまいましょう。
そうです、そういえばサンプルプログラム7はゲームです。それもアクションゲームです。
いよいよって感じですね。
だいたいは、これまでにおぼえたことの組み合わせで、できるようになっています。
と言っても、応用そしてまた応用なのはたしかなので、何回にもわけてじっくりやっていくことにしましょう。
どんなゲームなのか、とりあえず見てみましょう。
サンプルを遊んでみよう
ハカセ「いよいよクライマックスというカンジじゃのう。これは今のショクンにピッタリのサンプルプログラムじゃろう。」
LOAD”SAMPLE7”
OK
RUN
OK
RUN
インテリ「自機を左右に動かしながら、上からせまる敵をショットで打つゲームだね。」
神崎「十字ボタン左右で移動。画面タッチでショットっていうのはめずらしいね。」
ワンパク「いや……ちょっと待て、コレおかしいぞ! どうやっても負けにならねーじゃねェか!」
ハカセ「じゃから、タイトルが「侵略未遂 」となっとるじゃろ。カレらは、最後までシンリャクできなかったのじゃよ。カナしい話じゃな。」
ワンパク「いやそうじゃねェだろ! ナンのための残機ヒョウジだよ! だいたい敵をゼンブ倒しても特にナニも起きねー!」
ハカセ「ウム……、コレはそもそもユーザーショクンのチカラで、未完成のプログラムを完成させようというシュシなのじゃ……が……ちょっとムリがあったじゃろうか。」
神崎「まあ、そういうコトなら……いいの……かな?」
インテリ「そういうことにしておこうよ。今のところ気になるポイントは、
・敵にせめ込まれてもダメージがない
・敵をゼンブ倒しても終わらない
この2つかな?」
・敵にせめ込まれてもダメージがない
・敵をゼンブ倒しても終わらない
この2つかな?」
ワンパク「・敵のスピードが早すぎる
ってのもモンダイだぜ。」
ってのもモンダイだぜ。」
神崎「・Aボタンでショットにならない
のもやっぱりやりづらいよね。」
のもやっぱりやりづらいよね。」
ハカセ「ワシが言うのもなんじゃが、テキカクなシテキじゃな。
ホカにもプラスアルファのためにいくつか変数をしこんでおるんじゃが……」
ホカにもプラスアルファのためにいくつか変数をしこんでおるんじゃが……」
ワンパク「それはイイや、コレ以上ふやすとタイヘンそうだしな!」
ハカセ「ワシが言うコトでないかもしれんが、テキカクじゃのう……。」
再現をはじめてみよう
インテリ「プログラムを改造するには、まずプログラムをリカイした方がいいよね。せっかく総まとめのプログラムなんだから、イチから自分で作るつもりでやってみようか!」
神崎「カンタンそうに言うなあ……。」
インテリ「ムズカシく見えても、だいたいはこれまでのおさらいでデキるプログラムだよ。
たとえば、プログラムのサイショに何をすればいいのかはもうわかるよね。」
たとえば、プログラムのサイショに何をすればいいのかはもうわかるよね。」
ワンパク「そこはイマまでのサンプルと同じパターンでイケるだろうな。
」
0001#. ’┌──────────┐
0002#. ’│SAMPLE7 │
0003#. ’│ シンリャクミスイ │
0004#. ’└──────────┘
0005#. VISIBLE 1,1,0,0,0,0
0006#. CLS:COLOR 0
0007#. CLEAR
だいたいこんなモンか。本当はこのアトにDIM命令がくるんだろうが……。0002#. ’│SAMPLE7 │
0003#. ’│ シンリャクミスイ │
0004#. ’└──────────┘
0005#. VISIBLE 1,1,0,0,0,0
0006#. CLS:COLOR 0
0007#. CLEAR
0008#. DIM ???
配列変数のヨテイが立ってないから、トクに思いつかねェぜ!」
インテリ「そのあたりは後で出てくるだろうから、今はまだいいかな。
REMの’を行のはじめに入れて、メモとして残しておこうか。
REMの’を行のはじめに入れて、メモとして残しておこうか。
0008#. ’DIM ???
」ハカセ「いわゆる「コメントアウト」じゃな。プログラムを組みながらなら、こういうコメントの使い方もユウコウじゃぞ。」
動かしてみよう
ワンパク「ウーム……とりあえずプレイヤー機を出してはみたが……
0010#. ’---
0011#. LOCATE 10,21:PRINT”Г”;
0012#. LOCATE 0,22
0013#. PRINT”────────────────────────────────”;
」0011#. LOCATE 10,21:PRINT”Г”;
0012#. LOCATE 0,22
0013#. PRINT”────────────────────────────────”;
神崎「サンプルプログラム1のころにおぼえたコトだね。」
インテリ「このプレイヤーを動かすプログラムがいるだろうね。いまのうちにメインループを作っておこう。
0020#. ’---
0021#. @LOOP
0022#. GOSUB @MYSHIP
0023#. GOTO @LOOP
」0021#. @LOOP
0022#. GOSUB @MYSHIP
0023#. GOTO @LOOP
神崎「このラベル@MYSHIP(自機 )で、プレイヤーを動かすサブルーチンを作るんだね。」
ワンパク「サンプル3の方法で左右に動かすなら、こんなカンジだろ?
」
0025#. ’--- シ゛フ゛ン
0026#. @MYSHIP
0027#. B=BUTTON()
0028#. IF B AND 4 THEN ???
0029#. IF B AND 8 THEN ???
0030#. RETURN
だが、わからねえ! このIF文をどうすりゃ、プレイヤーが動くんだ?0026#. @MYSHIP
0027#. B=BUTTON()
0028#. IF B AND 4 THEN ???
0029#. IF B AND 8 THEN ???
0030#. RETURN
」
インテリ「そういえば、まだキャラクターが動くタイプのプログラムはやったことがなかったね。少しじっくり作ってみようか。
」
0011#. LOCATE 10,21:PRINT”Г”;
まずはこの行に注目かな。」
ワンパク「イチバンはじめのトコロじゃねェか! オレのヤリ方にモンクでもあるってのかよ!」
インテリ「このLOCATEの数字を変えると、プレイヤー機のバショも変わるのはなんとなくイメージできるかな?」
神崎「まあ、それくらいなら。
たとえばLOCATE 11,21:PRINT”Г”;と書けばもう1文字ぶん右に行くよね。」
たとえばLOCATE 11,21:PRINT”Г”;と書けばもう1文字ぶん右に行くよね。」
ワンパク「ソレと押されたボタンを組み合わせるのか……ツマリ、BUTTON()が押されたらLOCATEの数字を変える……? しかしLOCATEの数字を変えるには……」
神崎「あ、変数を使うんだ!」
ワンパク「! ……「数」が「変」わるから「変数」。そういうコトか……!」
インテリ「そうマチガってるワケでもないかな。数字がたびたび変わるようなトコロは、変数で作っておくとベンリだね。」
神崎「ということは、この行も……?
0011#. LOCATE 10,21:PRINT”Г”;
」インテリ「こんな感じがいいんじゃないかな。
プレイヤー のP。XとYはヨコ方向・タテ方向のイミだよ。
」
0011#. PX=10:PY=21
0012#. LOCATE PX,PY:PRINT”Г”;
変数の名前に使ったPは0012#. LOCATE PX,PY:PRINT”Г”;
」
ハカセ「数学で「座標」のヨコ方向に「x」、タテ方向に「y」を使うコトがモトモトのイミかのう。コンピューターのセカイでもヨコといえばX、タテといえばY、というコトが多いのじゃ。」
ワンパク「リクツはワカッてきたぜ。ボタンのあたりは、こうすりゃイイんだな?
」
0025#. ’--- シ゛フ゛ン
0026#. @MYSHIP
0027#. B=BUTTON()
0028#. IF B AND 4 THEN PX=PX-1
0029#. IF B AND 8 THEN PX=PX+1
0030#. LOCATE PX,PY:PRINT”Г”;
0031#. RETURN
左ボタンを押せばPXから1引いて、右ボタンを押せばPXに1足すってワケだ。そのアトにLOCATEしてPRINTすればバッチリだぜ!0026#. @MYSHIP
0027#. B=BUTTON()
0028#. IF B AND 4 THEN PX=PX-1
0029#. IF B AND 8 THEN PX=PX+1
0030#. LOCATE PX,PY:PRINT”Г”;
0031#. RETURN
」
ハカセ「さて、どうかのう? ためしにRUNしてみるかの。」
ワンパク「ウ、ウォオー! ナンだコリャアー!」
インテリ「アイデアはまちがってなかったけど、いくつかダイジなところが抜けていたね。
まず、B=BUTTON()から戻ってくるまでのループが早すぎるってこと。ボタンをチョンと押しただけで、ものすごいスピードで何度も押したことになってるんだな。」
まず、B=BUTTON()から戻ってくるまでのループが早すぎるってこと。ボタンをチョンと押しただけで、ものすごいスピードで何度も押したことになってるんだな。」
神崎「そういえばサンプルプログラム3でも、そんなコトがあったね。」
インテリ「となると、思い出すこともあるんじゃないかな?
」
0021#. @LOOP
0022#. GOSUB @MYSHIP
0023#. VSYNC 1
0024#. GOTO @LOOP
メインループの中にVSYNC命令をふやしたよ。0022#. GOSUB @MYSHIP
0023#. VSYNC 1
0024#. GOTO @LOOP
」
神崎「60分の1秒だけプログラムの動きを止めるんだったね。早すぎるループをわざと遅らせるのはワカるけど……60分の1秒って、そんなあっと言う間でいいの?」
インテリ「そのくらいでも、アクションゲームならイガイとちょうど良かったりするんだよ。ものたりなければ、増やせばすむコトだしね。」
ワンパク「ナルホドな。とにかくモンダイはカイケツだぜ。RUN!」
ワンパク「カイケツしきってねェー!」
動かし方のコツを学ぼう
ハカセ「ナニがおきておるのか、23行目をVSYNC 20ぐらいに変えて見るとハッキリするじゃろう。
こういう「重し 」をかけるのは、テストにはユウコウじゃぞい。」
こういう「
ワンパク「な……ナンとなくはワカッたな。ヨコに動かすと、プレイヤー機が分身するみたいに増えていっちまうんだ。」
インテリ「いちど画面にPRINTした字は、消さなきゃずっとそこに残っちゃうのさ。」
神崎「言われてみれば当たり前だけど……じゃあどうやって消せばいいの?」
インテリ「それはカンタンさ。” ”つまりスペースを同じ場所にPRINTすれば、Гはなくなるってワケだね。」
ワンパク「消すっつーか、上書きするっつーか、だな。
このプログラムだと、モトの場所にスペースを書けばイイんだから……ン? ブツブツ……ボタンが押されたらもうPXを変えてるワケで……モトの場所を消さないとイケねェんだけど、ボタンを押してないのに消したらマズいワケで……
イマイチわかんねェぞ!」
このプログラムだと、モトの場所にスペースを書けばイイんだから……ン? ブツブツ……ボタンが押されたらもうPXを変えてるワケで……モトの場所を消さないとイケねェんだけど、ボタンを押してないのに消したらマズいワケで……
イマイチわかんねェぞ!」
インテリ「これは、もっとプログラムを書き足さないといけないね。
」
0025#. ’--- シ゛フ゛ン
0026#. @MYSHIP
0027#. B=BUTTON():VX=0
0028#. IF B AND 4 THEN VX=-1
0029#. IF B AND 8 THEN VX=1
0030#. LOCATE PX,PY:PRINT” ”
0031#. PX=PX+VX
0032#. LOCATE PX,PY:PRINT”Г”;
0033#. RETURN
わかるかな? クッションになる変数VXを新しく作ったよ。0026#. @MYSHIP
0027#. B=BUTTON():VX=0
0028#. IF B AND 4 THEN VX=-1
0029#. IF B AND 8 THEN VX=1
0030#. LOCATE PX,PY:PRINT” ”
0031#. PX=PX+VX
0032#. LOCATE PX,PY:PRINT”Г”;
0033#. RETURN
」
神崎「ええと、ふだん変数VXは0で、ボタンを押したときだけ-1か1になるんだね。」
ワンパク「変数PXはまだ変わってねェから、まずスペースで消して……あらためてPXにVXを合わせてからLOCATEしなおしてГをPRINTするってワケか!
ワレながら、英語の多いコトバをしゃべっちまったぜ!」
ワレながら、英語の多いコトバをしゃべっちまったぜ!」
ハカセ「英語ついでに言うと、変数VXの「V」は「動く方向と量」という意味の「ベクター 」のコトじゃな。プログラムではよく使われるコトバじゃが、広義のベクトルと違って……」
神崎「ちょ、ちょっと待って! センモン的なハナシはいいんじゃないかな。
それより、ボタンが押されてない時にもいったんスペースで消して、同じ場所にもういちどГを書いているよね。これはいいの?」
それより、ボタンが押されてない時にもいったんスペースで消して、同じ場所にもういちどГを書いているよね。これはいいの?」
インテリ「RUNしてみるとわかるけど、すごいスピードで消しては書いてるから、そう気にはならないね。
でも、それがベストかというとビミョウかな。こう書くのが正しいのかもね。
動かない )まで飛んで、プレイヤー機をPRINTし直さないことにしたよ。
」
でも、それがベストかというとビミョウかな。こう書くのが正しいのかもね。
0025#. ’--- シ゛フ゛ン
0026#. @MYSHIP
0027#. B=BUTTON():VX=0
0028#. IF B AND 4 THEN VX=-1
0029#. IF B AND 8 THEN VX=1
0030#. IF VX==0 THEN @NOTMOVE
0031#. LOCATE PX,PY:PRINT” ”
0032#. PX=PX+VX
0033#. LOCATE PX,PY:PRINT”Г”;
0034#. ’---
0035#. @NOTMOVE
0036#. RETURN
ボタンが押されていないときは、イッキにラベル@NOTMOVE(0026#. @MYSHIP
0027#. B=BUTTON():VX=0
0028#. IF B AND 4 THEN VX=-1
0029#. IF B AND 8 THEN VX=1
0030#. IF VX==0 THEN @NOTMOVE
0031#. LOCATE PX,PY:PRINT” ”
0032#. PX=PX+VX
0033#. LOCATE PX,PY:PRINT”Г”;
0034#. ’---
0035#. @NOTMOVE
0036#. RETURN
」
ワンパク「コレで動きはバッチリってコトだな。RUNしてみるゼ!」
ワンパク「チ、チキショー!
画面のハジまで動かしたら、オカシなコトになっちまったぜ!」
画面のハジまで動かしたら、オカシなコトになっちまったぜ!」
神崎「それは、変数PXが画面を飛びこしちゃったのがゲンインかな?」
インテリ「PXが0のときに-1しちゃったり、PXが31のときに+1しちゃったり、だね。」
ワンパク「テメーら、もっとわかりやすいコトバでしゃべりヤガレー! 画面のハジまで行ったら、それよりムコウに動かさないようにすればいいだけじゃねえか!」
インテリ「これはワンパク君の言うとおりだね。ГをPRINTする前に、IF文を2行用意しておこうか。」
0032#. PX=PX+VX
0033#. IF PX<0 THEN PX=0
0034#. IF PX>31 THEN PX=31
0035#. LOCATE PX,PY:PRINT”Г”;
0033#. IF PX<0 THEN PX=0
0034#. IF PX>31 THEN PX=31
0035#. LOCATE PX,PY:PRINT”Г”;
神崎「これでプレイヤーの動きはモンダイなくなったね。」
ワンパク「コレはコレで、動いてねェプレイヤー機を消しては書いちまってるが……、モトのサンプルプログラムがこうだからシカタねェのか?」
ハカセ「し、しもうたァ━━ッ!」
インテリ「ま、まあそのあたりはコンゴのカダイとして……。
いったん、ココまでのプログラムをまとめておこう。
どういうイミなのか考えながらジッサイに打ち込んでみると、もっとよくワカると思うよ! モニタの前のみんなもやってみてね!」
いったん、ココまでのプログラムをまとめておこう。
どういうイミなのか考えながらジッサイに打ち込んでみると、もっとよくワカると思うよ! モニタの前のみんなもやってみてね!」
- キャラクターを動かすには
- たとえばLOCATEの位置を変数にして、BUTTON()の入力に合わせてIF文で変数を足したり引いたりすると、動いて見えます。
動く前にいた場所に、空白スペースを上書きして消してやると自然に見えそうですね。
LOCATEする場所が画面をはみださないように注意! - VSYNC命令とアクションゲームの関係
- プログラムを一時停止するVSYNC命令で、スピードを落とせます。早すぎて操作が追いつかない時にはとてもよく使いますね。