りょうのゲーム塾 -118ページ目

りょうのゲーム塾

再開、準備中。

チェックポイント
前回のサンプルに修正を行います。
修正の内容は移動速度の調整です。
現在の移動量はゲーム時間(1フレーム)あたり1づつ増加および減少していますが、移動速度が速いのでUFOを狙い撃ちするのが難しいと思われます。
そうなると移動速度を落とさなければなりません。
現在移動量が1なのでこれより少ないくするには少数点以下の量となるわけです。
プチコンで扱う数値変数は整数を扱う変数でなく、小数点以下の値を扱える固定小数点方式の実数です。
今度はこの実数で移動の量を調整してみましょう。


移動量を変数にして初期化して使うように修正します。
サンプルは下記の通りです。

■プログラム
0001 ' initialize
0002 GOSUB @SYS_INI
0003 GOSUB @UFO_INI
0004 GOSUB @PLY_INI
0005 ' game loop
0006 @LOOP
0007 GOSUB @SYS_MAIN
0008 ' task
0009 GOSUB @UFO_TASK
0010 GOSUB @PLY_TASK
0011 GOTO @LOOP
0012 '
0013 ' system
0014 '
0015 @SYS_INI
0016 SYS_CNT = 0
0017 RETURN
0018 '
0019 @SYS_MAIN
0020 VSYNC 1
0021 CLS
0022 SYS_CNT = SYS_CNT + 1
0023 SYS_KEY = BUTTON()
0024 RETURN
0025 '
0026 ' UFO task
0027 '
0028 @UFO_INI
0029 UFO_X = 0
0030 UFO_SX = 0.1
0031 UFO_F = 0
0032 RETURN
0033 '
0034 @UFO_TASK
0035 LOCATE UFO_X, 0
0036 PRINT "A"
0037 IF UFO_F!=0 GOTO @UFO_MVL
0038 ' move right
0039 UFO_X = UFO_X + UFO_SX
0040 IF UFO_X < 32 THEN RETURN
0041 UFO_X = 31
0042 UFO_F = 1
0043 RETURN
0044 ' move left
0045 @UFO_MVL
0046 UFO_X = UFO_X - UFO_SX
0047 IF UFO_X >= 0 THEN RETURN
0048 UFO_X = 0
0049 UFO_F = 0
0050 RETURN
0051 '
0052 ' player task
0053 '
0054 @PLY_INI
0055 PLY_X = 15
0056 PLY_SX = 0.5
0057 PLY_F = 0
0058 RETURN
0059 '
0060 @PLY_TASK
0061 LOCATE PLY_X,21
0062 PRINT "P"
0063 ON PLY_F GOTO @PLY_STOP,@PLY_MVR,@PLY_MVL
0064 STOP
0065 ' stop
0066 @PLY_STOP
0067 IF SYS_KEY AND 8 GOTO @PLY1
0068 IF SYS_KEY AND 4 GOTO @PLY2
0069 RETURN
0070 @PLY1
0071 PLY_F = 1
0072 RETURN
0073 @PLY2
0074 PLY_F = 2
0075 RETURN
0076 ' move right
0077 @PLY_MVR
0078 PLY_X = PLY_X + PLY_SX
0079 IF PLY_X > 31 THEN PLY_X = 31
0080 IF SYS_KEY AND 8 THEN RETURN
0081 PLY_F = 0
0082 RETURN
0083 ' move left
0084 @PLY_MVL
0085 PLY_X = PLY_X - PLY_SX
0086 IF PLY_X < 0 THEN PLY_X = 0
0087 IF SYS_KEY AND 4 THEN RETURN
0088 PLY_F = 0
0089 RETURN


まずは新しい命令について説明します。

■書式
ON 変数 GOTO @ラベル,@ラベル,...
変数で指定されるラベルへジャンプします。


・変更点1
サンプルでは63行目に使用しています。

0063 ON PLY_F GOTO @PLY_STOP,@PLY_MVR,@PLY_MVL
0064 STOP

ここでは変数PLY_Fの内容が0のとき@PLY_STOPへ、1のとき@PLY_MVRへ、2のとき@PLY_MVLへジャンプします。
PLY_Fが0以下もしくは3以上のときは64行目から実行します。
要するに変数の内容番目のラベルへジャンプします。(ただし、先頭は0番目です)
変数の内容が0以下でラベルの個数以上のときON GOTOの次の命令を実行します。
ここではバグ回避のためにSTOP命令で停止しています。

・変更点2
システム、UFOおよびプレイヤの初期化などもサブルーチンにしてまとめてあります。
この方がメインルーチンの動作が分かりやすくなります。

・変更点3
ラベルを統一しています。
これはプチコンのラベル名が8文字以下なので長いラベル名が使用できないためできるだけ短く統一しています。
UFOはもともと短いのでそのまま使用します。
PLAYERは長いのでPLYで変数名もラベルも統一します。
SYS_INI、UFO_INIおよびPLY_INIのINIはイニシャライズ(初期化)の意味です。
SYS_MAINはシステムの主なプログラムをまとめます。
UFO_TASKとPLY_TASKのTASKはタスクと呼ばれるキャラクタのプログラムのかたまりです。

・変更点4
UFOの移動量がUFO_SXに代入してあります。
プレイヤの移動量はPLY_SXに代入してあります。
これらのデータは調整しなければならないことが多いので変数に代入してあります。
プログラムの中で複数個所使用する場合に楽になります。
チェックポイント
BUTTON関数はDSiのボタン情報を2進数で返します。
どのボタンが押されているかを判断することでプログラムの流れを変えることができます。
そこで必要なのが論理演算です。


サンプルプログラムではプレイヤが右ボタンを押せば右に移動し、左ボタンを押せば左に移動しました。
左右のボタンが押されていなければ停止しています。
このようにプログラムの流れを変える切っ掛けとしてボタン情報を判定する必要があります。

実際にサンプルでは移動の判定に使っています。
まず39行目から41行目で

K = BUTTON()
IF K AND 8 GOTO @PLY1
IF K AND 4 GOTO @PLY2

そして54行目に

IF BUTTON() AND 8 THEN RETURN

そして62行目に

IF BUTTON() AND 4 THEN RETURN

ここで使っているのは10進数ですが実は2進数なのです。
数値の8は2進数に直すと1000です。
ただこのままでは10進数なのか2進数なのか分からないので今後2進数の場合数値の前の&Bと付け加えます。
10進数の8は2進数では&B1000となります。

ちなみに&BのBはバイナリ(binary)のことで2進数のことです。


まずBUTTON関数の返す値の意味を考えてみます。

■BUTTON関数

&B000000000000
  ┃┃┃┃┃┃┃┃┃┃┃┗ 十字ボタン上
  ┃┃┃┃┃┃┃┃┃┃┗━ 十字ボタン下
  ┃┃┃┃┃┃┃┃┃┗━━ 十字ボタン左
  ┃┃┃┃┃┃┃┃┗━━━ 十字ボタン右
  ┃┃┃┃┃┃┃┗━━━━ Aボタン
  ┃┃┃┃┃┃┗━━━━━ Bボタン
  ┃┃┃┃┃┗━━━━━━ Xボタン
  ┃┃┃┃┗━━━━━━━ Yボタン
  ┃┃┃┗━━━━━━━━ Lボタン
  ┃┃┗━━━━━━━━━ Rボタン
  ┃┗━━━━━━━━━━ STARTボタン
  ┗━━━━━━━━━━━ SELECTボタン


対応する位置が0のとき押されていない
1のとき押されているということです。

たとえばBUTTON関数の値が8のとき右へ移動するようにプログラムが作られています。このとき8は&B1000なので右から4番目の桁が1となります。
上の図では左から4番目は十字ボタン右になっていますね。

だったら右ボタンの判定は次の通りでもいいんじゃないかなと思いませんか?

IF BUTTON() == 8 THEN RETURN

実はこれでも動くことはあります。
ただこの判定はボタンが十字ボタン右のみの場合だけです。

しかし、実際のゲームの場合は複数のボタンが同時押されていることが多いので難しくなります。

たとえば十字ボタン右と十字ボタン上の同時押しの場合、これは右上ななめ移動に使用することが多いのですが、このときのBUTTON関数の返す値は

■BUTTON関数

&B000000001001
  ┃┃┃┃┃┃┃┃┃┃┃┗ 十字ボタン上
  ┃┃┃┃┃┃┃┃┃┃┗━ 十字ボタン下
  ┃┃┃┃┃┃┃┃┃┗━━ 十字ボタン左
  ┃┃┃┃┃┃┃┃┗━━━ 十字ボタン右
  ┃┃┃┃┃┃┃┗━━━━ Aボタン
  ┃┃┃┃┃┃┗━━━━━ Bボタン
  ┃┃┃┃┃┗━━━━━━ Xボタン
  ┃┃┃┃┗━━━━━━━ Yボタン
  ┃┃┃┗━━━━━━━━ Lボタン
  ┃┃┗━━━━━━━━━ Rボタン
  ┃┗━━━━━━━━━━ STARTボタン
  ┗━━━━━━━━━━━ SELECTボタン


これは10進数のいくらですか?
計算方法は今度にすることにして前回の表から

■10進数→2進数変換表

10進数┃ 2進数
━━━━╋━━━━
   0┃   0
   1┃   1
   2┃  10
   3┃  11
   4┃ 100
   5┃ 101
   6┃ 110
   7┃ 111
   8┃1000
   9┃1001 ←ここですね
  10┃1010
  11┃1011
  12┃1100
  13┃1101
  14┃1110
  15┃1111


要するに9になります。
8と比較しても等しくないので結果十字ボタン右が押されていないことになります。
このような場合に論理演算のANDを使います。

論理演算の特徴は各桁ごとに計算します。
ANDの場合一桁の演算結果は
■AND(論理積)

a┃b┃a AND b
━╋━╋━━━━━━━
0┃0┃   0
0┃1┃   0
1┃0┃   0
1┃1┃   1

ANDのことを論理積といいますが2進数一桁の掛け算と思えばいいのです。
ですのでどちらとも1のときだけ結果は1でそれ以外は0となります。

ではこの場合の十字ボタン右の判定を考えてみます。

BUTTON関数の値    &B1001
IFで使った値       &B1000  右の場合8でANDしましたね
ANDしてみると      &B1000

IF文は条件式の計算結果が0のとき条件が成り立たないと判断しそれ以外は成り立ったと判断します。
だかたこの場合結果が0でないので十字ボタン右が押されたと判定します。
このようなときにANDで使う値をマスクと呼んでいます。

あとよく聞く言葉でビットってありますよね。
この2進数一桁がビットといいます
チェックポイント
今回はプログラムの話をお休みして数値についてお話します。
これはプログラムを作るときに最低覚えておかないといけないことなので簡単に説明したいと思います。


【10進数について】

我々が使う数値には整数や実数があります。
そしてその殆どが10進数です。
あまりにも当たり前なのでピンとこないかもしれません。

要するに・・・
 0
 1
 2
 3
 4
 5
 6
 7
 8
 9
10


このように10で桁上がりするものを10進数といいます。

【2進数について】

コンピュータは実を言うと10進数を使っていはいません。
人が10進数を使うようになったのにはいろいろな説がありますが、
たぶん人間の指の数が片方に5本、合わせて10本だったからだと思われます。
物の数を数える必要があった人類は最初に自分の指を使って数を数えたと思います。
もっとも簡単な方法は物を数えるたびに一本ずつ指をまげて数えれば両腕で10個まで数えることができます。
しかし10個以上数えるためには指が足らないわけで・・・
そこで10個数えたらたとえば石を一個目の前に置けば次の10個を数えることができるわけです。これが桁上がりに当たるわけです。

ところがコンピュータ(正確に言うと現在のデジタルコンピュータ)はすべての信号をデジタルで扱っていてこのデジタル信号はL(低電圧、通常は0V)とH(高電圧、これは現在1Vから5Vまで様々です)の2つの状態で表されます。
要するに電気が通っているかいないか、スイッチが押されているかいないか、ランプが点いているかいないかなどの0か1の2つの値しか扱っていません。
そうなると数を数える際に10進数では一桁で0から9まで数えることができますが、コンピュータは一桁で0から1までしか数えることができないのです。

だから1まで数えたら2で桁上がりしなければなりません。これが2進数です。

では10進数で15まで数えてみます。

10進数    2進数
0      0
   1      1
   2     10
   3     11
   4    100
   5    101
   6    110
   7    111
   8   1000
   9   1001
  10   1010
  11   1011
  12   1100
  13   1101
  14   1110
  15   1111

となります。

実はこの2進数を前回のプログラムは使っていたのです。
どこで使っていたか分かりますか?