|

|
|
 |
7.1 待機飛行の敵 |
 |
|
|
|
|
|
敵はそれなりに複雑な動きをします。基本は画面の上の方で横移動ですが、アニメーションしたり飛んできたり、飛んでいるときは糞をしたりなどアピール度てんこ盛りですが、まずは基本の横移動+アニメーションする部分までを作ります。
時間があれば、2.ゲームの仕様で敵の待機飛行の仕様について確認してきてくださいな。
|
|
|
|
|
|
| Sheet1(ゲーム)のマクロ「(General)(Declarations)」への変数追加 |
|
|
|
|
(General)(Declarations)へ、敵用の変数を追加します。
一つ目は、敵のパターンを全消去するパターンを格納するrngClear16(Range型)です。これは、単に16x8の範囲を黒く塗りつぶすためのパターンなので、敵に限らず汎用的に使えます。
次に敵専用の変数ですが、まずは横位置と縦位置を格納するための変数rngEnemyX(Long型)とrngEnemyY(Long型)です。敵の数は5匹なので配列で5個、かつインデックスの範囲は1〜5にしました。
敵はアニメーションするので、どのパターンを表示するかを管理するための変数も必要です。それがrngEnemyPtn(Long型)です。これも同じように敵の最大数の5個配列を用意します。
rngEnemySt(Long型)は敵の状態を表す変数で、待機飛行しているのか、攻撃飛行しているのは、爆発中なのか、撃墜(画面に表示しない)された後なのかを管理するための変数です。同じく敵の最大数分の配列を用意します。
それと、rngEnemyWalkが敵の待機飛行パターンを格納する変数です。ワークシート上の絵を保存するのでRange型です。この変数はアニメーションのパターン数だけ必要なので配列で4個、かつインデックスの範囲は1〜4にしています。lngStage(Long型)は面数です。なお、lngStageは敵の縦位置の設定にも使います。
定数は、敵の状態(cstEnemyWalkが待機飛行、cstEnemyAttackが攻撃飛行、cstEnemyHit爆発、cstEnemyDownが撃墜)のコードを設定します。各値はおいらが独断で決めた値なので、なぜ1なのだ?なのてことは気にせずに(笑)
★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 lngStage As Long 'ステージ数
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 ' デモ画面
Const cstEnemyWalk As Long = 1 '敵待機飛行
Const cstEnemyAttack As Long = 2 '敵攻撃飛行
Const cstEnemyHit As Long = 8 '敵爆発中
Const cstEnemyDown As Long = 16 '敵撃墜
|
※このマクロは、ワークシート「ゲーム」へ記述してください。
灰色は既に作成済みの部分です。黒の部分を追加してください。
|
|
|
|
|
|
| Sheet1(ゲーム)のマクロ「prcAllInit」への処理追加 |
|
|
|
|
全体の初期設定(起動時の初期設定)には、敵のパターンと16x8消去用パターンの格納処理を追加します。敵の各パターンは、rngEnemyWalkのインデックス1〜4へRangeオブジェクトで設定、消去用パターンはrngClear16へ黒く塗りつぶすために用意した部分をRangeオブジェクトで設定します。なお、敵と消去用のパターンについては、3.2 キャラクタパターンの準備を参照してください。
★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))
'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))
'移動速度取得
lngMyShipS = Worksheets("コンフィグ").Range("B3") '自機
lngBeamS = Worksheets("コンフィグ").Range("B5") 'ビーム砲
'ゲーム画面の初期化
Call prcScreenInit
End Sub
|
※このマクロは、ワークシート「ゲーム」へ記述してください。
灰色は既に作成済みの部分です。黒の部分を追加してください。
|
|
|
|
|
|
| Sheet1(ゲーム)のマクロ「prcGameInit」への処理追加 |
|
|
|
|
ステージ毎の初期設定処理には、敵の位置や状態、アニメーションのパターン番号の設定処理などの初期処理を追加します。敵の状態はステージ開始毎に初期化する必要があるのでココで行います。
なお、敵の初期横位置と初期パターン番号の設定元はワークシート「コンフィグ」で、かつ配列なのでFor〜Nextを使っています。なお、Cellsの列指定でi+1としているのは、参照する列が2から始まるためです。
敵の縦位置はステージ数から算出(ステージ数×8)し、104を超える(ステージ14以降)場合はそれ以上大きくなりません。また、個別の横位置lngTmpY(n)には算出した縦位置(lngTmpY)を設定します。
★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
'敵の位置設定
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
'前回処理時刻初期化
lngMyShipB = GetTickCount() '自機
lngBeamB = GetTickCount() 'ビーム砲
'ゲーム画面の初期化
Call prcScreenInit
End Sub
|
※このマクロは、ワークシート「ゲーム」へ記述してください。
灰色は既に作成済みの部分です。黒の部分を追加してください。
|
|
|
|
|
|
| Sheet1(ゲーム)のマクロ「prcEnemyMove」の作成 |
|
|
|
|
敵の移動処理です。敵の動作のうち、基本の待機飛行の処理を作ります。
ラベルEnemyAttack以降の部分が待機飛行を行う部分です。まずは、待機飛行中であるかを判断しますが、これはlngEnemySt(i)から判断します。cstEnemyWalkなら待機飛行中なので待機飛行のパターンを画面へ描画します。描画するパターンは、lngEnemyPtn(n)で指定されているパターンです。
敵の移動(@以降)は、lngEnemyY(n)(敵の横位置)から1を引くことで行います。それと、1を引き続けるとそのうちlngEnemyX(n)(横位置)が1未満になりますが、1のときが最左なのでそれ以上は動けません(泣)。横位置0へ貼り付けなんて無茶なことをするとエラー400で怒られます。そんなわけで、1未満になったら強制的に右端へ移動(横位置へ130を設定)します。そうすれば、画面の左端へ達した敵が、右側から出現するように見えます。ちなみに、左端に達したとき(1未満になったとき)、敵の画を消去しておかないと画が残ったままになります。これではカッコ悪いので、ついでに強制消去(rngCelar16を貼り付ける)しておきましょう。
※強制消去時の横位置は1です。
あとは、パターンの切り替え。パターン番号へ1加算し、4を超えたらまた1から始める…を繰り返せば描画ごとに4種類の画を切り替えて表示できます。
ここまでの内容がラベルEnemyAttackで、この処理をFor〜Nextの所にあるGosubで呼び出し実行します。なぜGosubで呼び出すかと言うと…単に見やすくするためです(笑)。ちなみに、ループ回数は(5回)なので、このプロシジャ(prcEnemyMove)を1回呼び出すと敵5匹の処理が行われます。
なお、敵の移動(@)を行う条件は待機飛行中と攻撃飛行中ですが、待機飛行中のときはとにかく横に動かさなきゃ話になりません。じゃ、待機飛行中はというと…待機飛行中のときは描画ナシで横位置の計算だけになります。これは、攻撃飛行を終えた敵が待機飛行に戻るときの元の位置を覚えておくためです。
ちなみに、敵の状態は他に爆発中と撃墜がありますが、これらは次のステージになるまで解除されないので横移動処理などは行いません。
★Sheet1(ゲーム)のマクロ「prcEnemyMove」
Sub prcEnemyMove ()
'エクセルスマイル★シューティングゲームを作ろう
'処理概要:敵の制御を行う
'記述場所:ワークシート「ゲーム」
Dim i As Long
For i = 1 To 5
'待機飛行処理の呼び出し
GoSub EnemyWalk
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
End Sub
|
※このマクロは、ワークシート「ゲーム」へ記述してください。
灰色は既に作成済みの部分です。黒の部分を追加してください。
|
|
|
|
|
|
| Sheet1(ゲーム)のマクロ「prcGameMain」への処理追加 |
|
|
|
|
ゲームの主制御処理には、敵の移動処理の呼び出しを追加します。今のところは、移動速度のことは考えずに単に呼び出せばOKです。
★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
'敵の移動処理を呼び出す
Call prcEnemyMove
Loop
End Sub
|
※このマクロは、ワークシート「ゲーム」へ記述してください。
灰色は既に作成済みの部分です。黒の部分を追加してください。
|
|
|
|
|
|
| Sheet1(ゲーム)のマクロ「prcGame」への処理追加 |
|
|
|
|
全体を制御するための処理には、lngStage(ステージ数)の初期設定を追加します。なお、ステージ数は今のところ待機飛行中の敵縦位置の算出にしか使っていませんが、あとで色々使います。
★Sheet1(ゲーム)のマクロ「prcGame」
Sub prcGame()
'エクセルスマイル★シューティングゲームを作ろう
'処理概要:全体の主制御処理
'記述場所:ワークシート「ゲーム」
'変数の初期設定
Call prcAllInit
'主処理(永久にprcGameMainを呼び続ける)
'終了はEscキーを押す
Do Until False
'ステージ数の初期設定
lngStage = 1
'ゲームの主制御処理の呼び出し
Call prcGameMain
Loop
End Sub
|
※このマクロは、ワークシート「ゲーム」へ記述してください。
灰色は既に作成済みの部分です。黒の部分を追加してください。
|
|
|
|
|
|
|
|
|
|
サンプルのコードを全て定義したら、Sheet1のプロシジャ「prcGame」を実行しましょう。実行する際は、VBエディターからの実行ではなく、エクセルのツールバーにある (マクロの実行)ボタンを押し、マクロの一覧で「Sheet1.prcGame」を選択しましょう。
実行すると、敵が画面の上の方で左に歩いているでしょう…。あまりかわいくないですね。まぁ、敵だからかわいくても困りますが(汗)。そういえば、まだ速度の調整を入れてないのでいい加減なほど速いかもしれませんがご心配なく。あとで何とかします。
なお、実行すると永久ループと同じような状態になるのでタダでは停止できません。 (マクロの停止)ボタンが押せないのです。
でも、安心してください。Escキーを押すことで処理を止めることができます。
|
|
|
|
|