Casio Basic入門10
Casio Basic入門
誤字脱字・記載ミスや分かりにくい表現は随時追記・修正します
最終: 2015/01/07
最終: 2015/01/07
4. CasioBasicを使ってみる(続き)
Chapter 2 - 初級
◆ Chapter 2 の目標: 動きのあるプログラムを作る
簡単なアクションゲームを作る
前回: Casio Basic入門9
Chapter 2-1 で羽根が回るアニメーションを作りました。
プログラム名 CH2-1
50→C
Lbl 0
If C-4Int(C÷4)≦1
Then
Locate 8,2,"X"
Else
Locate 8,2,"+"
IfEnd
Dsz C
Goto 0
Locate 8,2," "
羽根が回る時間は、カウンターCで決まり、今はCが50に固定されています。反射ゲームでは、羽根が回る時間をランダムにします。
Chapter 2-2
ランダム関数を使う
fx-5800Pには、Ran# と RanInt# の2つのランダム関数が用意されています。
Ran#
0~1の間のランダムな小数を返します。
羽根を回す時間は、整数のカウンタC をランダムに設定する必要があります。そのためにはRan#が返す小数から整数を作る必要があります。例えば、2桁の整数を得るには、Int(100Ran#) とします。
RanInt#(L,H)
整数 L 以上、整数 H 以下の範囲でランダムな整数を返します。
羽根を回す時間は、整数のカウンタC をランダムに設定したいので、整数を返す RanInt#( ) 関数を用いる方がシンプルです。そこで、2~50の間の整数をランダムに得て、それをカウンタC に使うことにします。
そこで、50→C を RanInt#(2,50)→C に置き換えます。
RanInt#(2,50)→C
Lbl 0
If C-4Int(C÷4)≦1
Then
Locate 8,2,"X"
Else
Locate 8,2,"+"
IfEnd
Dsz C
Goto 0
Locate 8,2," "
ところで、ここで 0~50 の間の整数を得ようとして、RanInt#(0,50) とすると、たまに問題が発生します。つまりバグです。
RanInt#(0,50) は、0を返すことがあります。すると、カウンタ C が0になります。
この場合、Locate 8,2,"×" に続いて Dsz C が実行されると、Cが1つ減って-1になります。ループが回るに従ってC はどんどん減ってゆき、0になることが決してありません。ループを脱出するのはC が0になる時です。つまり、いつまでたってもループが回り続けるので、ゲームになりません。
では、RanInt#(1,50) はどうでしょうか?
1を返すときは早過ぎて、表示と同時に消えてしまい、ゲームとしては鬼仕様。実際に実行すると分かります。
そこで、RanInt#(2,50) としました。
これで、アニメーションを表示し、ランダムな時間が経過すると消える部分(ゲームの前半)ができました。
プログラム名 CH2-2
RanInt#(2,50)→C
Lbl 0
If C-4Int(C÷4)≦1
Then
Locate 8,2,"X"
Else
Locate 8,2,"+"
IfEnd
Dsz C
Goto 0
Locate 8,2," "
続いてプログラムの後半部分を作ります。
Chapter 2-3
再びGetkeyとDoループでカウンタ計測
プログラムの後半部分は、アニメーションが消えた後、キーを押すまでの反応時間を計測して、その結果を表示する機能です。
そのためには、何かキーが押されるまでループをまわし、ループの中でカウンタを増やしてゆく....これで反応時間を測定できます。キーが押されてループから抜けた時、カウンタの値を表示すれば、後半部分ができそうです。
今回は特定のキー、fx-5800P の [EXE] キーの隣にある [(-)] キーを押すことにして、このキーが押されたことの検出は Getkey を使います。そして、このキーが押されたらループから抜けて、その時のカウンタの数を表示するにコードを書いてゆきます。
さて、[(-)] キーのキーコードは、......Chapter 1 で作った Get Keycode プログラムで調べてみてください。DoループとGetkeyの使いこなしを、Chapter 1 で紹介しています。
或いは、プログラムライブラリ - キーコード取得 を参照してください。
先ずは、Do ループ:
Do
[処理]
LpWhile [ループ継続条件]
ここで、ループ継続条件は、「押されたキーが [(-)] でないこと」 となります。従って、
Do
[処理]
LpWhile Getkey≠57
となります。
次に、このループ内でカウンタを増やす処理を追加します。
Chapter 2-2 で作った部分でもカウンタC を使っています。カウンタは0からスタートさせる必要があり、0→Cで初期化しておくのが常道です。
ところで、アニメーションが終わった時は、このカウンタC は必ず0(ゼロ)になります。そして、今作るループでは、カウンタを0からスタートすれば良いので、そのままカウンタCを使えば良さそうですが、今後のプログラム変更でどうなるか分かりません。
もし、Cがゼロから始まらないようなプログラム変更を行い、その時、ゼロに初期化していないことを忘れていると、バグに悩むことになります。そこで、明示的に 0→C で初期化しておきましょう。
ループがまわるたびにカウンターを1づつ増やせば良いので、Isz C を使います。
[(-)] キーを押すとループから抜けるので、ループから抜けた直後にカウンターCの値を表示します。
これで、今回の追加部分がきそうです。
プログラム名 CH2-3
RanInt#(2,50)→C
Lbl 0
If C-4Int(C÷4)≦1
Then
Locate 8,2,"×"
Else
Locate 8,2,"+"
IfEnd
Dsz C
Goto 0
Locate 8,2," "
0→C
Do
Isz C
LpWhile Getkey≠57
Locate 8,2,C
今回追加した部分は、赤文字で示しています。
実際にプログラムを走らせてみてください。ゲームの基本的動作を確認できます。
Chapter 2-4
例外処理・例外フラグ・Breakコマンド
これまでに作ったプログラムを走らせて遊んでみます。
すると、アニメーションが表示されている時から、[(-)] キーを連打し続けると、1 を表示させることができてしまいます。フライングができるわけです。これではマズイ。ゲームになりません。
フライングしたらペナルティーを与えるとゲームらしくなります。
そこで、今回はフライングしたことを検知するようにします。具体的なペナルティーについては、点数の付け方やゲーム全体のルールをに即して、あとで考えることにします。
アニメーションを表示するループを抜き出します。
Lbl 0
If C-4Int(C÷4)≦1
Then
Locate 8,2,"×"
Else
Locate 8,2,"+"
IfEnd
Dsz C
Goto 0
このループの中で、[(-)] キーが押されたら、それはフライングです。
フライングを検出したら、直ちにループから抜け出し、さらに「フライング」と表示するように、プログラムを変更しようと思います。
[(-)] キーのキーコードは、57なので、Getkeyの戻り値を監視して、57になればループを抜けるようにすれはOKですね。
このループは、カウンタC がゼロになればループから抜けるようになっています。これら2つの条件でループを抜けるように変更しなければなりません。
そこで、Lbl/Goto + Dsz ループとは別に、Doループ + Dsz を使うと、2つの条件でループを抜ける方法が、簡単に実現できるので、ループ自体を Doループに変更します。
Do
If C-4Int(C÷4)≦1
Then
Locate 8,2,"×"
Else
Locate 8,2,"+"
IfEnd
Dsz C
LpWhile Getkey≠57
Lbl 0 / Goto 0 を Do / LpWhile Getkey≠57 に置き換えただけですが、Cがゼロになる時とキーコード57になる時の2つの条件でループを抜けられます。とても簡単に変更できました。
では次に、ループを抜けた後、フライングがあったことをを表示する方法を考えます。
本来のプログラムの流れとは別に、例外的なことが発生した時に対処することを「例外処理」と言います。今回のフライングを「例外処理」として扱うことにします。
例外処理は、本来のプログラムの流れとは別に、一括して処理するのが良い方法です。プログラムの構造を単純化し、流れを明確にするために役立ち、バグの発生を抑える効果があります。
複数の異なる例外に対しても、一カ所でまとめて処理するようにします(ゲームを完成させるためには、他の例外処理も必要になりそうです)。
そこで、例外が発生した時に、その例外の種類を「例外フラグ」という変数に記録し、例外1、例外2、例外3,といったように区別します。こうしておくと、例外を一括処理する時に、フラグの内容に応じて、場合分けをして処理を行います。
本来のルートからちょっと寄り道して例外処理を行って、それが終われば元のルートに戻る、これが例外処理です。
例外検知と例外フラグ
フライングは、ループで構成されるプログラムの流れを壊す例外事象なので、「フライングだゾ!」と表示し、さらにゲーム進行上の変数(点数など)を変更するのは、一括して 「例外処理」として扱うことにします。なお、例外が発生したことを記録しておく例外フラグの「フラグ」とは旗のことです。「例外が発生したゾ!」と旗を揚げるイメージですね。フラグの最初の概念は、0 か 1、つまり旗を下げるか挙げるかのどちらかでした。
しかし、例外フラグに整数を割り当てる方が便利です。例外が発生していない時は、フラグは0(ゼロ)、例外発生時には0以外の整数値を割り当てることで、例外の種類を区別して記録できます。
ここでは、変数 E を例外フラグとします。例外 = Exception (イクセプション )の頭文字をとって E としました。
・例外フラグ E は、例外が発生していない時はゼロと決めます。つまり最初はゼロに初期化します: 0→E
・フライングが発生した時は例外フラグ E の値を 1 とします: 1→E
すると、以下のように変更できます。
Do
If C-4Int(C÷4)≦1
Then
Locate 8,2,"×"
Else
Locate 8,2,"+"
IfEnd
Getkey=57⇒1→E
Dsz C
LpWhile E=0
※ 重要: 例外フラグ E は、プログラムの先頭部分で0に初期化しておく必要があります。
変更した部分を赤文字で示しています。Getkeyの戻り値が57の時、例外フラグ E に 1 を代入します。
ここで、If 文を使っても良いのでですが、より動作の速い ⇒(ジャンプ命令) を使いました。
LpWhile [ループ継続条件] の部分を、E=0 としました。例外が発生しなければ、例外フラグ E はゼロなので、この時はDoループを継続します。フライングと言う例外が発生して、例外フラグ E が 1 になると Doループを抜けます。
同時に、カウンタC がゼロになると、Dsz C のおかげで、LpWhile E=0 をジャンプして、次へ進んでループを抜けられます。
今後、フライング以外に新たな例外に対応する必要になれば、例外フラグ E に、2、3...と別の整数を割り当てます。その場合でも、Eは 0 以外ですから、ループを抜けられます。
以上をまとめます。
0→E
RanInt#(2,50)→C
Do
If C-4Int(C÷4)≦1
Then
Locate 8,2,"×"
Else
Locate 8,2,"+"
IfEnd
Getkey=57⇒1→E
Dsz C
LpWhile E=0
Locate 8,2," "
そして、キーを押すまでの反応時間を測定して表示を行う以下の処理が続きます。
0→C
Do
Isz C
LpWhile Getkey≠57
Locate 8,2,C
さて、フライングをした場合は、反応時間の計測は不要で、直ちにこのブロックを通り抜けて欲しい。
そこで、フライングした時、つまり例外フラグEが1の時に、直ちにDoループを抜けるようにします。そこで、CasioBasicに備わっているBreakコマンドを使います。Breakコマンドはループから抜けだすコマンドです。
※ CasioBasicコマンドリファレンス
- Break
そこで、以下のようにプログラムを変更します(赤文字が変更部分)。
0→C
Do
E=1⇒Break
Isz C
LpWhile Getkey≠57
Locate 8,2,C
If E=1
Then
Locate 3,2,"FALSE START"
IfEnd
Doループの中では、Eが1 ならば Break を実行して、ループから抜けます。
Doループが終われば、例外処理を一括して行う部分です。Eが1ならは「フライング」と表示を行います。
※ フライングは和製英語なので英語としては通じません。そこで FALSE START (不正スタート)と表示することにします。
これで、フライング検知と表示を盛り込むことができました。
プログラム名 CH2-4
0→E
RanInt#(2,50)→C
Do
If C-4Int(C÷4)≦1
Then
Locate 8,2,"×"
Else
Locate 8,2,"+"
IfEnd
Getkey=57⇒1→E
Dsz C
LpWhile E=0
Locate 8,2," "
0→C
Do
E=1⇒Break
Isz C
LpWhile Getkey≠57
Locate 8,2,C
If E=1
Then
Locate 3,2,"FALSE START"
IfEnd
改行を使って機能ブロックに分けています。CasioBasicでは、このように改行を入れてもエラーになりません。
1ブロック: 初期化
2ブロック: アニメーション表示(フライング検出)
3ブロック: 反応時間計測と表示
4ブロック: 例外処理(フライング表示)
次回は、これまで作ったプログラムを繰り返すようにし、さらに得点を計算させて、ゲーム仕様に近づけてゆきます。
つづく...
⇒ CasioBasic入門11 / 目次
応援クリックをお願いします。励みになるので...
- 関連記事
-
-
Casio Basic入門36 2015/01/15
-
Casio Basic入門35 2015/01/09
-
Casio Basic入門10 2015/01/07
-
Casio Basic入門34 2015/01/02
-
Casio Basic入門33 2014/12/31
-