6.3 自機とビーム砲の速度調整
ここまでの状態でもかなりゲームらしくなってきましたが、ビーム砲を発射しているときと発射していないときでは全体の動きが目に見えて違うし、それ以前に動きが速すぎます。これではゲームとしてのバランスが悪いので、適度な速さ&ビーム砲を発射しているときと発射していないときの速さの差がなくなるよう調節します。

なお、エクセルマクロTips〜ゲーム篇〜5.1 速度調整に速度調整に関するネタがあるので、参考までにどうぞ。
速度が落ちる原因
たとえば、速度調整前のプロシジャ「prcGameMain」内に次のような処理があります。

'主処理(ステージクリアかゲームオーバーになるまで実行)
'強制終了はEscキーを押す
Do Until lngGameStatus = cstStageClear or lngGameStatus = cstGameOver

   '自機の移動処理を呼び出す
   Call prcMyShipMove

   'ビーム砲フラグが発射状態(ture)のときはビーム砲処理を呼び出す
   If blnBeamF Then
      Call prcBeamMove
   End If

Loop

ループ1回ごとに自機とビーム砲(ビーム砲は発射状態のとき)の描画処理を行っています。早い話が全力疾走してるんです。全力疾走なので、処理には全く余裕がありません。余力がないからビーム砲を発射したときにスピードが落ちるんです。そもそも、全力疾走しているので全体的に速すぎます(笑)

それじゃどうする?ということになりますが、意外と単純。全力疾走しないようにします。例えば自機は軽く走る、ビーム砲はちょいダッシュって感じにすればOK!

全力疾走しないための方法(速さを調整する方法)は色々ありますが、基本は時間の経過を使う方法です。もっとも簡単な方法は「時間の経過を監視する方法」で、「前回その物体に関する処理を行ってから0.n秒経過していないときは、その物体の処理をしない」ということを物体毎に行います。
Sheet1(ゲーム)のマクロ「(General)(Declarations)」への変数追加
(General)(Declarations)へ、自機とビーム砲の移動速度を管理するための変数を追加します。追加するのは、自機の移動速度(lngMyShipS)と前回の処理時刻(lngMyShipB)、ビーム砲の移動速度(lngBeamS)とビーム砲の前回の処理時刻(lngBeamB)です。


 ★Sheet1(ゲーム)のマクロ「(General)(Declarations)」
Option Explicit

'エクセルスマイル★シューティングゲームを作ろう
'記述場所:ワークシート「ゲーム」
'記述箇所:(General)(Declarations)

Dim lngGameStatus as Long 'ゲームの状態

Dim lngMyShipX As Long  '自機の横位置
Dim rngMyShip  As Range '自機のパターン
Dim blnBeamF   As Boolean 'ビーム砲発射フラグ
Dim lngBeamX   As Long    'ビーム砲横位置
Dim lngBeamY   As Long    'ビーム砲縦位置
Dim rngBeam    As Range   'ビーム砲のパターン

Dim rngClear8  As Range   '8x8の消去用パターン

Dim lngMyShipS As Long    '自機の移動速度
Dim lngMyShipB As Long    '自機の前回処理時刻
Dim lngBeamS   As Long    'ビーム砲の移動速度
Dim lngBeamB   As Long    'ビーム砲の前回処理時刻

Const cstFKeyLeft    As Long = 37 '左ボタン
Const cstFKeyRight   As Long = 39 '右ボタン
Const cstFKeyV     As Long = 86 'Vボタン

Const cstPlay        As Long = 1 'ゲーム中
Const cstStageClear  As Long = 2 'ステージクリア
Const cstGameOver    As Long = 4 ' ゲームオーバー
Const cstDemo        As Long = 8 ' デモ画面
 ※このマクロは、ワークシート「ゲーム」へ記述してください。
  灰色は既に作成済みの部分です。黒の部分を追加してください。
Sheet1(ゲーム)のマクロ「prcAllInit」への処理追加
全体の初期設定(起動時の初期設定)には、移動速度の設定処理を追加します。移動速度の設定は、起動時に一度だけ行っておけば良いのでこのプロシジャで行います。

移動速度の元になる情報はワークシート「コンフィグ」から取得しますが、その設定内容は3.1 ワークシートの準備と設定自機移動速度ビーム砲移動速度です。なお、これらの値の単位はミリ秒です。


 ★Sheet1(ゲーム)のマクロ「prcAllInit」
Sub prcAllInit()

    'エクセルスマイル★シューティングゲームを作ろう
    '処理概要:アプリケーション全体の初期設定を行う
    '記述場所:ワークシート「ゲーム」

    'ゲームの状態を設定
    lngGameStatus = cstPlay

    '自機のパターンを設定
    Set rngMyShip = Range(Cells(201, 1), Cells(208, 16))

    'ビーム砲のパターンを設定
    Set rngBeam = Range(Cells(217, 1), Cells(224, 8))

    '8×8のパターン消去用
    Set rngClear8 = Range(Cells(217, 33), Cells(224, 40))

    '移動速度取得
    lngMyShipS = Worksheets("コンフィグ").Range("B3") '自機
    lngBeamS = Worksheets("コンフィグ").Range("B5") 'ビーム砲

    'ゲーム画面の初期化
    Call prcScreenInit

End Sub
 ※このマクロは、ワークシート「ゲーム」へ記述してください。
  灰色は既に作成済みの部分です。黒の部分を追加してください。
Sheet1(ゲーム)のマクロ「prcGameInit」への処理追加
ステージ毎の初期設定処理には、自機とビーム砲の前回処理時刻へ現在の時刻を設定する処理を追加します。ちなみに、現在時刻はAPIのGetTickCountで取得した時刻です。


 ★Sheet1(ゲーム)のマクロ「prcGameInit」
Sub prcGameInit ()

    'エクセルスマイル★シューティングゲームを作ろう
    '処理概要:ステージ毎の初期設定を行う
    '記述場所:ワークシート「ゲーム」

    '自機の横位置設定
    lngMyShipX = 1

    'ビーム砲フラグをOFF
    blnBeamF = False

    '前回処理時刻初期化
    lngMyShipB = GetTickCount() '自機
    lngBeamB = GetTickCount()   'ビーム砲

    'ゲーム画面の初期化
    Call prcScreenInit

End Sub
 ※このマクロは、ワークシート「ゲーム」へ記述してください。
  灰色は既に作成済みの部分です。黒の部分を追加してください。
Sheet1(ゲーム)のマクロ「prcGameMain」への処理追加
ゲームの主制御処理には、自機とビーム砲の移動処理の呼び出しに速度調整用の制限を加えます。

加える制限は「GetTickCountで取得した(ミリ秒の)現在時刻と前回処理を行った時刻(これもGetTickCountで取得したミリ秒の時刻)の差が、一定の秒数を超えたときだけ処理をする」という内容です。


 ★Sheet1(ゲーム)のマクロ「prcGameMain」
Sub prcGameMain()

    'エクセルスマイル★シューティングゲームを作ろう
    '処理概要:ゲームの主制御処理
    '記述場所:ワークシート「ゲーム」

    'ゲームの初期設定
    Call prcGameInit

    '主処理(ステージクリアかゲームオーバーになるまで実行)
    '強制終了はEscキーを押す
    Do Until lngGameStatus = cstStageClear or lngGameStatus = cstGameOver

       '自機の移動。
       '前回処理時刻から一定の時間が過ぎたとき処理を行う
       If GetTickCount() - lngMyShipB > lngMyShipS Then

          '自機の移動処理を呼び出す
          Call prcMyShipMove

          '自機の移動処理を行った時刻を保存(次回処理のため)
          lngMyShipB = GetTickCount()

       End If

       'ビーム砲/前回処理時刻から一定の時間が過ぎたときだけ処理
       If GetTickCount() - lngBeamB > lngBeamS Then

          'ビーム砲フラグが発射状態(ture)のときはビーム砲処理を呼び出す
          If blnBeamF Then
             Call prcBeamMove
          End If

          'ビーム砲の移動処理を行った時刻を保存(次回処理のため)
          lngBeamB = GetTickCount()

       End If

    Loop

End Sub
 ※このマクロは、ワークシート「ゲーム」へ記述してください。
  灰色は既に作成済みの部分です。黒の部分を追加してください。
というわけで実験!
サンプルのコードを全て定義したら、Sheet1のプロシジャ「prcGame」を実行しましょう。実行する際は、VBエディターからの実行ではなく、エクセルのツールバーにある(マクロの実行)ボタンを押し、マクロの一覧で「Sheet1.prcGame」を選択しましょう。

実行すると、今度は自機とビーム砲がそれなりの速さで動きます。それと、ビーム砲を発射したとたんに速度が落ちることはありません。

なお、実行すると永久ループと同じような状態になるのでタダでは停止できません。(マクロの停止)ボタンが押せないのです。

でも、安心してください。Escキーを押すことで処理を止めることができます。
Copyright(C) 1999-2006 結城圭介。 All rights reserved