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

りょうのゲーム塾

再開、準備中。

チェックポイント
今までゲームループの中でキャラが一度ずつ実行されています。この単位をタスクと呼んでいますが、では具体的にはどういうものかというと…

一般的な多くのゲーム機の場合1秒間に60回ほど画面を描画しゲームを実行しています。
これを通常60fpsといいます。
fpsとはフレーム・パー・セカンドの意味です。
1秒間に描画する画面数のことです。
今までプログラム中に使用していたVSYNCは垂直ブランキング同期というもので1秒間に60回発生します。
この垂直ブランキングをゲーム内の時間の基準として使用しているのです。
実際にそれを確かめるためにサンプルプログラムを作りました。
実行してみてください。


■プログラム
0001 ' V-Blanking Sync test
0002 C = 0
0003 S = 0
0004 CLS
0005 @LOOP
0006 VSYNC 1
0007 C = C + 1
0008 IF C != 60 GOTO @LOOP
0009 C = 0
0010 S = S + 1
0011 LOCATE 0, 0
0012 PRINT S
0013 GOTO @LOOP



プログラムの解説です。

0002 C = 0
0003 S = 0

C はカウンタです。0を代入し初期化しています。
S はセカンド…要するに秒数です。これも0で初期化してあります。

0004 CLS

画面を初期化します。

0005 @LOOP
0006 VSYNC 1

ゲームループの同期を行います。
この部分が画面の垂直同期を待ちゲームループの最初を認識する方法です。

0007 C = C + 1
0008 IF C != 60 GOTO @LOOP
0009 C = 0

ゲームループは1秒間に60回なので C に1ずつ足し60になったら1秒ということですよね?
1秒になっていないならゲームループの同期へジャンプします。
60回になっていれば1秒たったことになります。
再度次の60回をクントするために C は0で初期化します。

0010 S = S + 1

60カウントで1秒たったことになるので S に1を加えます。
この S の内容が進んだ時間(秒数)となります。

0011 LOCATE 0, 0
0012 PRINT S
0013 GOTO @LOOP

画面0,0の位置に経過した秒数を表示します。
そのあとまたゲームループ同期へジャンプします。

これを実行すると画面に秒数が表示されます。
大体1秒おきに表示されていると思います。

ただ!!
実際の時間より若干長いんです。本当は^^;
そこは誤差としておいてください。

サンプルで作ってるゲームにはSYS_CNTという変数があります。
実はこっそりシステムが時間を管理するためにカウントを行っています。
チェックポイント
今度は武器を追加してみましょう。
敵のUFOやプレイヤなどのキャラと同じように武器を作成します。


■プログラム
0001 ' initialize
0002 GOSUB @SYS_INI
0003 GOSUB @UFO_INI
0004 GOSUB @PLY_INI
0005 GOSUB @WPN_INI
0006 ' game loop
0007 @LOOP
0008 GOSUB @SYS_MAIN
0009 ' task
0010 GOSUB @UFO_TASK
0011 GOSUB @PLY_TASK
0012 GOSUB @WPN_TASK
0013 GOTO @LOOP
0014 '
0015 ' system
0016 '
0017 @SYS_INI
0018 SYS_CNT = 0
0019 RETURN
0020 '
0021 @SYS_MAIN
0022 VSYNC 1
0023 CLS
0024 SYS_CNT = SYS_CNT + 1
0025 SYS_KEY = BUTTON()
0026 RETURN
0027 '
0028 ' UFO task
0029 '
0030 @UFO_INI
0031 UFO_X = 0
0032 UFO_SX = 0.1
0033 UFO_F = 0
0034 RETURN
0035 '
0036 @UFO_TASK
0037 LOCATE UFO_X, 0
0038 PRINT "A"
0039 IF UFO_F!=0 GOTO @UFO_MVL
0040 ' move right
0041 UFO_X = UFO_X + UFO_SX
0042 IF UFO_X < 32 THEN RETURN
0043 UFO_X = 31
0044 UFO_F = 1
0045 RETURN
0046 ' move left
0047 @UFO_MVL
0048 UFO_X = UFO_X - UFO_SX
0049 IF UFO_X >= 0 THEN RETURN
0050 UFO_X = 0
0051 UFO_F = 0
0052 RETURN
0053 '
0054 ' player task
0055 '
0056 @PLY_INI
0057 PLY_X = 15
0058 PLY_SX = 0.5
0059 PLY_F = 0
0060 RETURN
0061 '
0062 @PLY_TASK
0063 LOCATE PLY_X,21
0064 PRINT "P"
0065 IF SYS_KEY AND 16 THEN GOSUB @WPN_FIRE
0066 ON PLY_F GOTO @PLY_STOP,@PLY_MVR,@PLY_MVL
0067 STOP
0068 ' stop
0069 @PLY_STOP
0070 IF SYS_KEY AND 8 GOTO @PLY1
0071 IF SYS_KEY AND 4 GOTO @PLY2
0072 RETURN
0073 @PLY1
0074 PLY_F = 1
0075 RETURN
0076 @PLY2
0077 PLY_F = 2
0078 RETURN
0079 ' move right
0080 @PLY_MVR
0081 PLY_X = PLY_X + PLY_SX
0082 IF PLY_X > 31 THEN PLY_X = 31
0083 IF SYS_KEY AND 8 THEN RETURN
0084 PLY_F = 0
0085 RETURN
0086 ' move left
0087 @PLY_MVL
0088 PLY_X = PLY_X - PLY_SX
0089 IF PLY_X < 0 THEN PLY_X = 0
0090 IF SYS_KEY AND 4 THEN RETURN
0091 PLY_F = 0
0092 RETURN
0093 '
0094 ' weapon task
0095 '
0096 @WPN_INI
0097 WPN__F = 0
0098 WPN_SY = 0.5
0099 RETURN
0100 '
0101 @WPN_TASK
0102 ON WPN_F GOTO @WPN_WAIT,@WPN_MOVE
0103 STOP
0104 '
0105 @WPN_WAIT
0106 RETURN
0107 '
0108 @WPN_MOVE
0109 LOCATE WPN_X,WPN_Y
0110 PRINT "!"
0111 WPN_Y = WPN_Y + WPN_SY
0112 IF WPN_WPN_Y >= 0 THEN RETURN
0113 WPN_F = 0
0114 RETURN
0115 '
0116 @WPN_FIRE
0117 IF WPN_F THEN RETURN
0118 WPN_F = 1
0119 WPN_X ~ PLY_X
0120 WPN_Y = 20
0121 RETURN


では追加部分の説明を行います。

0001 ' initialize
0002 GOSUB @SYS_INI
0003 GOSUB @UFO_INI
0004 GOSUB @PLY_INI
0005 GOSUB @WPN_INI
0006 ' game loop
0007 @LOOP
0008 GOSUB @SYS_MAIN
0009 ' task
0010 GOSUB @UFO_TASK
0011 GOSUB @PLY_TASK
0012 GOSUB @WPN_TASK
0013 GOTO @LOOP


まずはメイン部分の変更です。
ここでは新たに武器の初期化と武器のタスク実行を追加してあります。
具体的な内容は後ほど!!

0062 @PLY_TASK
0063 LOCATE PLY_X,21
0064 PRINT "P"
0065 IF SYS_KEY AND 16 THEN GOSUB @WPN_FIRE
0066 ON PLY_F GOTO @PLY_STOP,@PLY_MVR,@PLY_MVL
0067 STOP


UFO部分では変更はありませんでした。
プレイヤ部分ではSYS_KEYに16をANDしてそれが0かそうでないか判断しています。
SYS_KEY変数はシステムがゲームループ1回につき一度BUTTON関数を呼び出しその値を保存しています。
ゲームループは1秒間に60回(理想的には)実行されます。
そのときのDSiのボタンの状態をSYS_KEY変数に保存しています。
16でANDするとAボタンが押されているかどうかが判定できます。

要するにここではAボタンが押されていたら@WPN_FIREサブルーチンを呼ぶことになります。
@WPN_FIREは武器の発射を行うルーチンです。

0096 @WPN_INI
0097 WPN__F = 0
0098 WPN_SY = 0.5
0099 RETURN


武器の初期化を行います。
WPN_Fが0のとき武器は発射されていない状態で発射されるのを待っています。
WPN_SYは武器のY方向の移動量です。

0101 @WPN_TASK
0102 ON WPN_F GOTO @WPN_WAIT,@WPN_MOVE
0103 STOP
0104 '
0105 @WPN_WAIT
0106 RETURN
0107 '
0108 @WPN_MOVE
0109 LOCATE WPN_X,WPN_Y
0110 PRINT "!"
0111 WPN_Y = WPN_Y + WPN_SY
0112 IF WPN_WPN_Y >= 0 THEN RETURN
0113 WPN_F = 0
0114 RETURN


ON WPN_F GOTO 文で武器が待ち状態か発射されて移動している状態か判断しています。
0103行のSTOPは普通は実行されません。
WPN_Fに不正なデータが入っているときストップします。
要するにバグチェック用のSTOPです。

@WPN_WAITは何もしません。

@WPN_MOVEは武器がY方向に移動します。
このときY方向の位置を保存しているWPN_Yが0以上の場合には画面ないですが
0未満のときは画面外となるため武器の状態を待ち状態にしています。

0116 @WPN_FIRE
0117 IF WPN_F THEN RETURN
0118 WPN_F = 1
0119 WPN_X ~ PLY_X
0120 WPN_Y = 20
0121 RETURN


Aボタンが押されたときに呼び出しているWPN_FIREは武器を発射状態にします。

ただし最初の0117行目はWPN_FをIF文で判断しています。
WPN_Fが0のとき武器は待ち状態なのでいつでも発射できますが、
WPN_Fが0以外のときは発射済みなので何もせず戻ります。
要するに武器は1個だけ使えるということです。
すでに武器を使用してる場合には新たに発射できません。(今回は!!)

発射できる場合まずフラグを発射状態に変更します。
次に武器の初期位置を初期化します。
プレイヤのY位置が21なのでひとつ上の位置ということでWPN_Yに20を設定しています。
発射した時のプレイヤのX方向の位置はPLY_Xが持っているのでその値をWPN_Xに代入しています。
これでプレイヤの横位置は同じで縦がひとつ上の位置に武器を表示できます。

ではなぜわざわざプレイヤのX方向の位置を入れるのでしようか?
そうです!!
プレイヤはあなたの操作で動いています。
もし武器がプレイヤのX座標を使って表示していたら…これは一回試してみてください。
前々回のタイトルで2進→10進を間違えて10進→2進と書いてしまいました。

申し訳ありませんm(__)m

あと、最近お仕事のほうが忙しくて更新できていません重ねて

申し訳ありませんm(__)m

少々飽きの来る内容だったので本日中にプログラミングの追加を行います。