|

|
|
 |
7.3 速度調整 |
 |
|
|
|
|
|
| Sheet1(ゲーム)のマクロ「(General)(Declarations)」への変数追加 |
|
|
|
|
(General)(Declarations)へ、待機飛行と攻撃飛行の移動速度を管理するための変数を追加しますが、ここまで来れば細かい説明はいらないでしょう…決して手抜きではないです(汗)
★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 rngClear16 As Range '16x8の消去用パターン
Dim lngEnemyX(1 To 5) As Long '敵の横位置
Dim lngEnemyY(1 To 5) As Long '敵の縦位置
Dim lngEnemyPtn(1 To 5) As Long '敵待機飛行のパターン番号
Dim lngEnemySt(1 To 5) As Long '敵の状態
Dim rngEnemyWalk(1 To 4) As Range '敵待機飛行のパターン
Dim blnEnemyAttackSt As Boolean '攻撃飛行中の敵有無
Dim lngEnemyAttackX As Long '攻撃飛行中の縦位置
Dim lngEnemyAttackY As Long '攻撃飛行中の横位置
Dim lngEnemyAttackDir As Long '攻撃飛行中の移動方向
Dim rngEnemyAttack As Range '攻撃飛行中のパターン
Dim lngStage As Long 'ステージ数
Dim lngMyShipS As Long '自機の移動速度
Dim lngMyShipB As Long '自機の前回処理時刻
Dim lngBeamS As Long 'ビーム砲の移動速度
Dim lngBeamB As Long 'ビーム砲の前回処理時刻
Dim lngEnemyWalkS As Long '敵待機飛行の移動速度
Dim lngEnemyWalkB As Long '敵待機飛行の前回処理時刻
Dim lngEnemyAttackS As Long '敵攻撃飛行の移動速度
Dim lngEnemyAttackB 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 ' デモ画面
Const cstEnemyWalk As Long = 1 '敵待機飛行
Const cstEnemyAttack As Long = 2 '敵攻撃飛行
Const cstEnemyHit As Long = 8 '敵爆発中
Const cstEnemyDown As Long = 16 '敵撃墜
|
※このマクロは、ワークシート「ゲーム」へ記述してください。
灰色は既に作成済みの部分です。黒の部分を追加してください。
|
|
|
|
|
|
| Sheet1(ゲーム)のマクロ「prcAllInit」への処理追加 |
|
|
|
|
全体の初期設定(起動時の初期設定)では、敵の移動速度のうち「攻撃飛行」の移動速度設定を行います。攻撃飛行の移動速度は変化しない(=ゲームの起動時に1度だけ行っておけばよい)ため、この処理で初期化してます。
なお、待機飛行の移動速度(lngEnemyWalkSの値)は、ゲーム中に変化する(敵の数が減る毎に移動速度を速める)ため、ステージクリア毎に最初の値に戻さなければなりません。そのため、ゲームの初期処理「prcGameInit」で行います。
※「prcGameInit」は、最終的にはステージクリア毎に1回動作する処理になります
★Sheet1(ゲーム)のマクロ「prcAllInit」
Sub prcAllInit()
'エクセルスマイル★シューティングゲームを作ろう
'処理概要:アプリケーション全体の初期設定を行う
'記述場所:ワークシート「ゲーム」
'乱数を初期化
Randomize
'ゲームの状態を設定
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))
'16x8のパターン消去用
Set rngClear16 = Range(Cells(217, 33), Cells(224, 48))
'敵待機飛行のパターン
Set rngEnemyWalk(1) = Range(Cells(209, 1), Cells(216, 16))
Set rngEnemyWalk(2) = Range(Cells(209, 17), Cells(216, 32))
Set rngEnemyWalk(3) = Range(Cells(209, 33), Cells(216, 48))
Set rngEnemyWalk(4) = Range(Cells(209, 49), Cells(216, 64))
'敵攻撃飛行のパターン
Set rngEnemyAttack = Range(Cells(209, 65), Cells(216, 80))
'移動速度取得
lngMyShipS = Worksheets("コンフィグ").Range("B3") '自機
lngBeamS = Worksheets("コンフィグ").Range("B5") 'ビーム砲
lngEnemyAttackS = Worksheets("コンフィグ").Range("B7") '敵攻撃飛行
'ゲーム画面の初期化
Call prcScreenInit
End Sub
|
※このマクロは、ワークシート「ゲーム」へ記述してください。
灰色は既に作成済みの部分です。黒の部分を追加してください。
|
|
|
|
|
|
| Sheet1(ゲーム)のマクロ「prcGameInit」への処理追加 |
|
|
|
|
ステージ毎の初期設定処理には、待機飛行の移動速度(lngEnemyWalkS)の設定と、敵の前回処理時刻(lngEnemyWalkBとlngEnemyAttackB)へ現在時刻を設定する処理を追加します。ちなみに、現在時刻はAPI/GetTickCountで取得した時刻を設定します。
★Sheet1(ゲーム)のマクロ「prcGameInit」
Sub prcGameInit ()
'エクセルスマイル★シューティングゲームを作ろう
'処理概要:ステージ毎の初期設定を行う
'記述場所:ワークシート「ゲーム」
Dim i As Long '汎用変数
Dim lngTmpY As Long ' 敵の縦位置調整用
'自機の横位置設定
lngMyShipX = 1
'ビーム砲フラグをOFF
blnBeamF = False
'敵の基準縦位置設定
'ステージ数を元に基準位置を算出
'104を超えたときはそれ以上、下へ表示しない
lngTmpY = lngStage * 8
If lngTmpY > 104 Then
lngTmpY = 104
End If
'敵の待機飛行の移動速度再設定
lngEnemyWalkS = Worksheets("コンフィグ").Range("B6")
'敵の位置設定
For i = 1 To 5
lngEnemyX(i) = Worksheets("コンフィグ").Cells(11, i + 1) '敵の横位置
lngEnemyY(i) = lngTmpY '敵の縦位置
lngEnemyPtn(i) = Worksheets("コンフィグ").Cells(13, i + 1) '敵待機のパターン番号
lngEnemySt(i) = cstEnemyWalk '敵の状態
Next
'攻撃飛行中の敵はナシ
blnEnemyAttackSt = False
'前回処理時刻初期化
lngMyShipB = GetTickCount() '自機
lngBeamB = GetTickCount() 'ビーム砲
lngEnemyWalkB = GetTickCount() '敵待機飛行
lngEnemyAttackB = GetTickCount() '敵攻撃飛行
'ゲーム画面の初期化
Call prcScreenInit
End Sub
|
※このマクロは、ワークシート「ゲーム」へ記述してください。
灰色は既に作成済みの部分です。黒の部分を追加してください。
|
|
|
|
|
|
| Sheet1(ゲーム)のマクロ「prcEnemyMove」への処理追加 |
|
|
|
|
敵の移動処理「prcEnemyMove」へ速度調整処理を追加した内容です。待機飛行と攻撃飛行の各処理はGosubで呼び出しているので、この呼び出しを「前回の処理から移動速度で指定された時間を経過した場合のみ」呼び出すようにします。
※Gosubで行ったのはここで分かりやすいようにするためで、プログラムの処理効率を考えた場合Gosubは使わない方がいい場合があります。
しかし、Gosubを呼び出す条件が「時間が経過しているか」としていないのがポイント。というのも、敵の移動処理はFor〜Nextで5回ループしているので、Gosubを呼び出す都度判定した場合は「前の敵を動かしてからn秒後」(待機飛行の場合)ということになり少々意味が変わってしまいます。(ループしている間に時間が過ぎるからです)
そのため、For〜Nextに入る前に状態毎の移動可否判定を行い、移動OKのときはフラグをTrue、For〜Next内では「フラグがTrueなら移動処理を実行」という流れにしています。
★Sheet1(ゲーム)のマクロ「prcEnemyMove」
Sub prcEnemyMove ()
'エクセルスマイル★シューティングゲームを作ろう
'処理概要:敵の制御を行う
'記述場所:ワークシート「ゲーム」
Dim i As Long
Dim blnWalk As Boolean
Dim blnAttack As Boolean
'待機飛行を行う時間になっているかを判定
If GetTickCount() - lngEnemyAttackB > lngEnemyAttackS Then
blnWalk = True '経過した
lngEnemyAttackB = GetTickCount()
Else
blnWalk = False 'まだ
End If
'攻撃飛行を行う時間になっているかを判定
If GetTickCount() - lngEnemyWalkB > lngEnemyWalkS Then
blnAttack = True '経過した
lngEnemyWalkB = GetTickCount()
Else
blnAttack = False 'まだ
End If
For i = 1 To 5
'攻撃飛行処理の呼び出し
'ただし、一定時間が経過している場合のみ
If blnWalk = True Then
GoSub EnemyAttack
End If
'待機飛行処理の呼び出し
'ただし、一定時間が経過している場合のみ
If blnAttack = True Then
GoSub EnemyWalk
End If
Next
Exit Sub
'-------------------------------------------------------
EnemyWalk: '待機飛行処理
'-------------------------------------------------------
'敵が待機飛行のとき
If lngEnemySt(i) = cstEnemyWalk Then
'敵を表示
rngEnemyWalk(lngEnemyPtn(i)).Copy _
Destination:=Range(Cells(lngEnemyY(i), lngEnemyX(i)), _
Cells(lngEnemyY(i) + 7, lngEnemyX(i) + 15))
End If
'敵の移動とパターンの切り替え (@)
'待機飛行中と攻撃飛行中の場合のみ行う
If lngEnemySt(i) = cstEnemyWalk Or _
lngEnemySt(i) = cstEnemyAttack Then
'敵を左へ移動する
lngEnemyX(i) = lngEnemyX(i) - 1
'rangeの指定でマイナスなどを指定すると400のエラーが出る
'右端まで達したら、左端へ移動
If lngEnemyX(i) < 1 Then
rngClear16.Copy _
Destination:=Range(Cells(lngEnemyY(i), 1), _
Cells(lngEnemyY(i) + 7, 16))
lngEnemyX(i) = 130
End If
'パターン番号の切り替え
'4以上になったら1から
lngEnemyPtn(i) = lngEnemyPtn(i) + 1
If lngEnemyPtn(i) > 4 Then
lngEnemyPtn(i) = 1
End If
End If
Return
'-------------------------------------------------------
EnemyAttack: '攻撃飛行処理
'-------------------------------------------------------
'攻撃飛行に移る判定1「通常」
'攻撃飛行中の敵がナシ、Rndの結果が5以下、待機飛行中なら攻撃飛行へ移る
'攻撃飛行の開始位置は待機飛行中の位置
'横移動の方向は最初は0(横移動ナシ)
If blnEnemyAttackSt = False And Int(Rnd * 1000) < 5 And _
lngEnemySt(i) = cstEnemyWalk Then
lngEnemySt(i) = cstEnemyAttack '攻撃飛行中
blnEnemyAttackSt = True '攻撃飛行中あり
lngEnemyAttackX = lngEnemyX(i) '攻撃飛行開始横位置設定
lngEnemyAttackY = lngEnemyY(i) '攻撃飛行開始縦位置設定
lngEnemyAttackDir = 0 '横の移動方向 この値を移行中の横位置へ加算
End If
'攻撃飛行処理
If lngEnemySt(i) = cstEnemyAttack Then
'攻撃飛行の敵を表示
rngEnemyAttack.Copy _
Destination:=Range(Cells(lngEnemyAttackY, lngEnemyAttackX), _
Cells(lngEnemyAttackY + 7, lngEnemyAttackX + 15))
'25%の確立で横移動方向を変化
If Int(Rnd * 100) < 25 Then
'-1 , 0, 1の結果が得られる
lngEnemyAttackDir = Int(Rnd * 3) - 1
End If
'縦位置へ1加算(下へ移動)
lngEnemyAttackY = lngEnemyAttackY + 1
'縦位置が143を超えたら最下段到達
'攻撃飛行を終了し待機飛行へ戻る
If lngEnemyAttackY > 143 Then
rngClear16.Copy _
Destination:=Range(Cells(143, lngEnemyAttackX), _
Cells(150, lngEnemyAttackX + 15))
lngEnemySt(i) = cstEnemyWalk
blnEnemyAttackSt = False
End If
'横位置へlngEnemyAttackDirを加算
'lngEnemyAttackDirの内容は -1 , 0, 1
lngEnemyAttackX = lngEnemyAttackX + lngEnemyAttackDir
'横位置が1未満になったらそれ以上左へ移動しない
If lngEnemyAttackX < 1 Then
lngEnemyAttackX = 1
End If
'横位置が130以上になったらそれ以上右へ移動しない
If lngEnemyAttackX > 130 Then
lngEnemyAttackX = 130
End If
End If
Return
End Sub
|
※このマクロは、ワークシート「ゲーム」へ記述してください。
灰色は既に作成済みの部分です。黒の部分を追加してください。
|
|
|
|
|
|
|
|
|
|
サンプルのコードを全て定義したら、Sheet1のプロシジャ「prcGame」を実行しましょう。実行する際は、VBエディターからの実行ではなく、エクセルのツールバーにある (マクロの実行)ボタンを押し、マクロの一覧で「Sheet1.prcGame」を選択しましょう。
ここまで作ると、かな〜りゲームっぽくなったと思いませんか?待機飛行の敵はのんびり歩き、攻撃飛行の敵は猛スピード(?)で飛んでくるでしょう。ここまで来ると、ビーム砲が当たっても敵を撃墜できないのがツライですね(汗)。というわけで、次は敵を撃墜する部分を作ってみましょう。
なお、実行すると永久ループと同じような状態になるのでタダでは停止できません。 (マクロの停止)ボタンが押せないのです。
でも、安心してください。Escキーを押すことで処理を止めることができます。
|
|
|
|
|