|

|
|
 |
10.1 敵の糞攻撃 |
 |
|
|
|
|
|
さて、とうとう来ました練習問題。練習問題は「敵の糞攻撃を作る」です。これまでの練習問題の出し方を反省(笑)し、今回からは穴埋め形式に限りなく近くしました。一部、穴埋めとは言えない部分もありますが…(汗)
敵の糞攻撃は一瞬難しそうに聞こえますが、ここまでの内容を読破&マスターしていれば簡単です。というより、今までに覚えてきたことを試すのにちょうど良いぐらいですよ!
|
|
|
|
|
|
|
|
|
|
まずは、糞攻撃がどんなタイミングで行われるかを確認しておきましょう。基本的な仕様は「2.ゲームの仕様」を参照してください。
敵が糞攻撃をしてくるのは「攻撃飛行」をしているときです。攻撃飛行中に7%ぐらいの確立で糞をしますが、敵が糞攻撃をするのは敵の縦位置が100未満の場合という制限を付けます。これより下ですると自機は糞まみれ…じゃなくて衝突する以外に手がなくなってしまうからです。
それと、糞は右図の位置あたりから発射され、その後下に向かって落ちて行き、画面の最下段(下図参照)に達すると消滅します。なお、糞の移動速度は攻撃飛行の敵と同じにしますが、移動量を2セルずつにして攻撃飛行の敵より早く動くようにします。

また、糞は単純に下に落ちるのではなく、攻撃中の敵の動きに合わせて横移動が加わります。横移動の量は、とりあえず1セルで良いでしょう。もし、糞が右端や左端に達したときは跳ね返るように逆方向に動きます。
糞はビーム方で打ち落とすことも可能です。もちろん、その場で爆発します。なお、糞を打ち落とした場合の得点は大判振る舞いの50点です。もちろん、「それじゃ安すぎる!!」と思ったときは好きな得点にしてかまいません(笑)。なお、ビーム砲で撃墜するときは範囲は図の通りで、たとえかすっても当たりです。
なお、自機が糞と当たる範囲は右図ぐらいの範囲内にしておきます。おそらく、敵本体よりは柔らかい(謎)ので、多少かするぐらいは平気なのでしょう(笑)。というのは冗談で、あまりシビアにしてもバランスが悪いかな…と思ったからです。
|
|
|
|
|
|
| Sheet1(ゲーム)のマクロ「(General)(Declarations)」への変数追加 |
|
|
|
|
(General)(Declarations)へ、敵の糞に関する変数と定数を追加します。糞攻撃を追加するために必要な変数と定数は次の通りです。
★Sheet1(ゲーム)のマクロ「(General)(Declarations)」へ追加する内容
Dim rngFunAttack As Range '糞のパターン
Dim rngFunHit As Range '糞の爆発パターン
Dim blnFunAttack As Boolean '糞攻撃有無
Dim lngFunX As Long '糞の横位置
Dim lngFunY As Long '糞の縦位置
Dim lngFunDirect As Long '糞の横移動方向
Dim lngFunSt As Long '糞の状態
Dim lngFunS As Long '糞の移動速度
Dim lngFunB As Long '糞の前回処理時刻
Dim lngFunHitS As Long '糞の爆発パターン描画速度
Dim lngFunHitB As Long '糞の爆発パターン前回描画時間
Dim lngFunhitC As Long '糞爆発時の描画回数
Const cstFunAttack As Long = 1 '糞落下中
Const cstFunHit As Long = 2 '糞爆発中
|
※このマクロは、ワークシート「ゲーム」へ記述してください。
追加するものだけを載せておきます。
|
|
|
|
|
|
| Sheet1(ゲーム)のマクロ「prcAllInit」への処理追加 |
|
|
|
|
全体の初期設定(起動時の初期設定)には、落下中の糞のパターンの保存(rngFunAttackへ保存)と爆発中の糞のパターンの保存(rngFunHitへ保存)設定、移動速度を管理する変数lngFunS(Long型)への初期設定処理を追加します。ちなみに、lngFunSにはワークシート「コンフィグ」から値を取得します。
次の処理を、プロシジャ「prcAllInit」の適切な場所へ追加してください。
★Sheet1(ゲーム)のマクロ「prcAllInit」へ追加する処理
'糞の設定
Set rngFunAttack = Range(Cells(217, 17), Cells(224, 24)) '落下中の糞
Set rngFunHit = Range(Cells(217, 25), Cells(224, 32)) '爆発中の糞
lngFunS = Worksheets("コンフィグ").Range("B9") '糞移動速度
lngFunHitS = Worksheets("コンフィグ").Range("B10") '糞爆発パターン描画速度
|
|
|
|
|
|
|
| Sheet1(ゲーム)のマクロ「prcGameInit」への処理追加 |
|
|
|
|
ステージ毎の初期設定処理には、糞攻撃の有無を管理する変数blnFunAttackの初期設定のみです。Falseが糞攻撃をしていない、Tureが糞攻撃中(糞が飛んでいる)です。初期値は糞攻撃をしていない(False)に設定します。
次の処理を、プロシジャ「prcGameInit」の適切な場所へ追加してください。
★Sheet1(ゲーム)のマクロ「prcGameInit」へ追加する処理
'糞攻撃をしていない
blnFunAttack = False
|
|
|
|
|
|
|
| Sheet1(ゲーム)のマクロ「prcGameMain」への処理追加 |
|
|
|
|
ゲームの主制御処理には、糞の移動処理「prcFunMove」の呼び出しを加えます。呼び出し条件は、糞攻撃の有無を管理する変数blnFunAttackが糞攻撃アリ(True)のときです。
このプロシジャは、とりあえず次のようにしておけば良いでしょう。なお、これと同じ処理をデモ画面処理「prcDemoMode」へ追加すると、デモ画面中も糞をするようになります。
★Sheet1(ゲーム)のマクロ「prcGameMain」
Sub prcGameMain()
'エクセルスマイル★シューティングゲームを作ろう
'処理概要:ゲームの主制御処理
'記述場所:ワークシート「ゲーム」
'ゲームの初期設定
Call prcGameInit
'主処理(ステージクリアかゲームオーバーになるまで実行)
'強制終了はEscキーを押す
Do Until lngGameStatus = cstStageClear or lngGameStatus = cstGameOver
'自機の移動。自機が爆発していないとき、かつ
'前回処理時刻から一定の時間が過ぎたとき処理を行う
If blnMyShipLock = False And _
GetTickCount() - lngMyShipB > lngMyShipS Then
'自機の移動処理を呼び出す
Call prcMyShipMove
'自機の移動処理を行った時刻を保存(次回処理のため)
lngMyShipB = GetTickCount()
End If
'自機の爆発処理。敵と衝突するとblnMyShipLockがTrueになる。
'前回処理時刻から一定の時間が過ぎたときだけ処理
If blnMyShipLock = True And _
GetTickCount() - lngMyShipHitB > lngMyShipHitS Then
Call prcMyShipDown
lngMyShipHitB = GetTickCount()
End If
'ビーム砲/前回処理時刻から一定の時間が過ぎたときだけ処理
If GetTickCount() - lngBeamB > lngBeamS Then
'ビーム砲フラグが発射状態(ture)のときはビーム砲処理を呼び出す
If blnBeamF Then
Call prcBeamMove
End If
'ビーム砲の移動処理を行った時刻を保存(次回処理のため)
lngBeamB = GetTickCount()
End If
'敵の移動処理を呼び出す
Call prcEnemyMove
'糞移動処理の呼び出し
If blnFunAttack = True Then
Call prcFunMove
End If
Loop
'ステージクリア処理
lngStageClearB = GetTickCount() '処理開始時の時刻を取得
Do While lngGameStatus = cstStageClear
'メッセージの描画
'本当は1回だけ描けばいいけど、シンプルに毎回描画しています
rngStageClear.Copy _
Destination:=Range(Cells(66, 61), Cells(70, 87))
'描画時間の制御
If GetTickCount() - lngStageClearB > lngStageClearS Then
'ゲームの状態をプレイ中に
lngGameStatus = cstPlay
'ステージ数へ1加算
lngStage = lngStage + 1
End If
Loop
'ゲームオーバー処理
lngGameOverB = GetTickCount() '処理開始時の時刻を取得
Do While lngGameStatus = cstGameOver
'メッセージの描画
'本当は1回だけ描けばいいけど、シンプルに毎回描画しています
rngGameOver.Copy _
Destination:=Range(Cells(52, 61), Cells(56, 102))
'描画時間の制御
If GetTickCount() - lngGameOverB > lngGameOverS Then
'ゲームの状態をデモに
lngGameStatus = cstDemo
'ハイスコアの更新
If lngScore > lngHighScore Then
'変数の値を更新
lngHighScore = lngScore
'ハイスコアをワークシートへ書き込み
Worksheets("コンフィグ").Range("B16") = lngHighScore
'各種ダイアログを表示しない
Application.DisplayAlerts = False
'ワークシートの保存
ThisWorkbook.Save
'各種ダイアログを表示する
Application.DisplayAlerts = True
End If
End If
Loop
End Sub
|
※このマクロは、ワークシート「ゲーム」へ記述してください。
灰色は既に作成済みの部分です。黒の部分を追加してください。
|
|
|
|
|
|
| Sheet1(ゲーム)のマクロ「prcEnemyMove」への処理追加 |
|
|
|
|
敵の移動処理の攻撃飛行処理(EnemyAttack)へ、糞攻撃の開始処理を追加します。穴埋め問題となっているので、足りない部分を付け加えてください。
攻撃飛行中で糞攻撃をしていない(blnFunAttackがFalse)とき、一定の高さ(縦位置が100未満)にいるなら7%ぐらいの確立で糞攻撃を行います。
糞攻撃の準備は、糞攻撃の有無を管理する変数blnFunAttackへTrueを設定し、他に移動速度や糞の初期位置の設定と、糞の状態(lngFunSt)へcstFunAttackを設定します。初期位置は攻撃飛行中の敵の位置が基準で右図の辺りです。
ちなみに、糞の横移動方向(lngFunDirect)には敵の横移動方向(lngEnemyAttackDir)をそのまま入れておけばOKです。
★Sheet1(ゲーム)のマクロ「prcEnemyMove」
長くなったので別ウィンドウで表示するようにしました。ここをクリックしてくださいな。
|
|
|
|
|
|
| Sheet1(ゲーム)のマクロ「prcFunMove」の新規作成 |
|
|
|
|
糞の移動処理です。このプロシジャは新たに作成します。ただし、穴埋め問題となっているので、足りない部分を付け加えてください。
基本的には、落下中(lngFunStがcstFunAttack)と爆発中(lngFunStがcstFunHit)の2通りの処理があり、落下中であれば縦移動、ビーム砲との衝突判定、最下段まで達したときの糞攻撃終了処理が必要、爆発中は爆発パターンを描画し、一定回数描画したら、糞攻撃の終了処理を行います。
ちなみに、糞は落下に加えて左右にも移動します。もしも画面の左右の端に達したら、跳ね返るように逆方向へ動くようにしましょう。
★Sheet1(ゲーム)のマクロ「prcFunMove」
別ウィンドウで表示するようにしました。ここをクリックしてくださいな。
|
|
|
|
|
|
|
|
|
|
サンプルのコードを全て定義したら、Sheet1のプロシジャ「prcGame」を実行しましょう。実行する際は、VBエディターからの実行ではなく、エクセルのツールバーにある (マクロの実行)ボタンを押し、マクロの一覧で「Sheet1.prcGame」を選択しましょう。
どうでしょう?敵が糞攻撃をしかけてくるようになったでしょうか。もし400というエラーが出たら、描画出来ない範囲へ描画していたり、コピー元と貼り付け先の範囲が合っていなかったりなどが考えられます。
また、「一度は糞攻撃を仕掛けてくるけど、その後全く仕掛けてこない」なんてときは、糞の後始末処理(サブルーチンFunEnd)で糞攻撃有無ステータスのblnFunAttackをFalseにしているかをチェックしてみるとよいです。
なお、実行すると永久ループと同じような状態になるのでタダでは停止できません。 (マクロの停止)ボタンが押せないのです。
でも、安心してください。Escキーを押すことで処理を止めることができます。
|
|
|
|
|