前回はセル移動周りの処理を解説&修正を行いました。
今回はセル移動周りの後半戦です。
次にやらないといけないのがいよいよ各種セル毎のイベント実行です。
ここがゲームの肝の部分なので細かく解説していきたいと思います。
前回のおさらい
前回はプレイヤーの移動処理前半部分のソースを解説&修正を行いました
プロシージャ名も以下のように変更しています。
Sub MovePlayer()
↓
Sub Worksheet_SelectionChange()
セルの移動処理をしてもらうためにどうしても必要だったので止む無く…。
今回はSub Worksheet_SelectionChange()の後半戦でセルのイベント処理を解説と実際に動かしてとりあえず遊んでみるのパートになります。
3.移動 Worksheet_SelectionChange で各種イベントを実行!?(後半)
後半のソースはイベントの実行処理部分ですね。移動した結果そのセル(配列)にあるイベントが実行される処理が書かれています。
移動処理後半のソースはこちら
' 移動先のセルの内容によって処理を分岐
Select Case grid(newX, newY)
Case GridCell.Empty
' 空のセルなら何もしない
Case GridCell.Enemy
' 敵がいるセルなら攻撃する
AttackEnemy()
Case GridCell.Item
' アイテムがあるセルなら取得する
PickupItem()
Case GridCell.Pitfall
' 落とし穴があるセルならダメージを受ける
TakeDamage(3)
Case GridCell.Door
' 扉があるセルなら鍵を持っているか確認して開ける
If playerHasKey Then
' 扉を開けてクリア
MsgBox "クリア!"
Else
MsgBox "鍵が必要です。"
End If
End Select
' 移動先に移動する
playerX = newX
playerY = newY
End Sub
上記のソースは配列にセットされているイベントの内容をCase文で読み取り、イベントを実行する仕組みです。
因みに…以下の変数名は変更しました。
第2話でも書きましたが、Emptyは予約語なので使えません。なので、Empに直しておきましょう。
基本的には図解の通りの処理をするだけなので、難しいことはありません。
最後にPlayer位置を最新の値に変更しています。
' 移動先に移動する
playerX = newX
playerY = newY
さて、問題はここからなのです。肝心のイベントの中身が書かれていない箇所が何か所かあります。
以下のAttackEnemy()とPickItem()は移動した先のソースコードは空っぽなので、現時点では何も起きません。
Case GridCell.Enemy
' 敵がいるセルなら攻撃する
AttackEnemy()
Case GridCell.Item
' アイテムがあるセルなら取得する
PickupItem()
因みにAttackEnemy()やPickItem()の後ろの()は削除しないとエラーが出るので今回は削除しておきます。
さて、もう二か所修正しておきましょう。それはPitfallです。
Pitfall(落とし穴)に落ちた時に分かるようにする
Pitfallはちゃんと動作するのですが、落とし穴に落ちても見た目でダメージを受けたことが分かりません。
なのでソースに以下の記述を追加します。
追記する箇所はCase GridCell.PitfallにあるTakeDamage(3)の下に追記すればOKです。
Case GridCell.Pitfall
' 落とし穴があるセルならダメージを受ける
TakeDamage(3)
MsgBox "落とし穴に落ちた。プレイヤーは3のダメージ!"
これで落とし穴に落ちたときにダメージを受けたことがわかります。
あと、もう一つ直さないといけないところがあります。
鍵を取得した際のイベントを作る
実はこのソースコードないんですよ。なので、Case文の中に以下のコードを追記しました。
Case GridCell.Key
'鍵を取得する
playerHasKey = True
MsgBox "鍵を手に入れた"
鍵を手に入れないと永遠にクリアできないので、この記述は必須です。
これで少なくともゲームが最低限出来る状態が整いました。
ChatGpt RPGゲームの第5話時点のソースコード
さて、以下が現時点でのソースコードです。
そう言いながら…何か所か修正してしまった箇所もあるので、そこも少し説明します。
ソースコードはこちら
Option Explicit
' グリッドの幅と高さを定義
Const GRID_WIDTH As Integer = 10
Const GRID_HEIGHT As Integer = 10
' グリッドのセルごとに定義する内容
Enum GridCell
Emp
Enemy
Item
Pitfall
Door
Key
End Enum
' キャラクターの初期位置
Dim playerX As Integer
Dim playerY As Integer
' キャラクターの状態
Dim playerHP As Integer
Dim playerHasKey As Boolean
Dim playerAttackPower As Integer
' グリッドの内容を保持する配列
Dim grid(GRID_WIDTH, GRID_HEIGHT) As GridCell
' 初期化処理
private Sub Init()
' グリッドの内容をランダムに設定
Dim x As Integer, y As Integer
For x = 1 To GRID_WIDTH
For y = 1 To GRID_HEIGHT
Dim randValue As Integer
randValue = Int(Rnd() * 4) ' 0-3のランダムな整数を生成
grid(x, y) = randValue
Cells(x, y).Interior.ColorIndex = 20
Next y
Next x
'鍵の配置
randValue = Int(Rnd() * 9 + 1) ' 1-10のランダムな整数を生成
x = randValue
randValue = Int(Rnd() * 9 + 1) ' 1-10のランダムな整数を生成
y = randValue
grid(x, y) = 5
'扉の配置
Do
randValue = Int(Rnd() * 9 + 1) ' 1-10のランダムな整数を生成
x = randValue
randValue = Int(Rnd() * 9 + 1) ' 1-10のランダムな整数を生成
y = randValue
Loop While grid(x, y) = 5 ' 鍵の位置と重なる場合はやり直す
grid(x, y) = 4
' キャラクターの初期位置を設定
playerX = 1
playerY = 1
Sheet1.Cells(playerY, playerX).Activate
' キャラクターの初期状態を設定
playerHP = 10
playerHasKey = False
playerAttackPower = 1
End Sub
' ワークシートのセル上をキャラクターが移動する
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
If Not Intersect(Target, Range("A1:J10")) Is Nothing Then
' セルが10x10のマップの範囲内である場合
Dim moveX As Integer
Dim moveY As Integer
moveX = 0
moveY = 0
Select Case True
' 上キー
Case Target.Row > playerY
moveY = 1
' 下キー
Case Target.Row < playerY
moveY = -1
' 左キー
Case Target.Column < playerX
moveX = -1
' 右キー
Case Target.Column > playerX
moveX = 1
End Select
playerY = playerY + moveY
playerX = playerX + moveX
Sheet1.Cells(playerY, playerX).Activate
Cells(playerY, playerX).Interior.ColorIndex = 35
End If
' キャラクターの配列上の移動判定処理
Dim newX As Integer
newX = playerX
If newX < 1 Or newX > GRID_WIDTH Then
' 移動先がグリッド外なら何もしない
Exit Sub
End If
Dim newY As Integer
newY = playerY
If newY < 1 Or newY > GRID_HEIGHT Then
' 移動先がグリッド外なら何もしない
Exit Sub
End If
' 移動先のセルの内容によって処理を分岐
Select Case grid(newX, newY)
Case GridCell.Emp
' 空のセルなら何もしない
Case GridCell.Enemy
' 敵がいるセルなら攻撃する
AttackEnemy
Case GridCell.Item
' アイテムがあるセルなら取得する
PickupItem
Case GridCell.Pitfall
' 落とし穴があるセルならダメージを受ける
TakeDamage (3)
MsgBox "落とし穴に落ちた。プレイヤーは3のダメージ!"
Case GridCell.Door
' 扉があるセルなら鍵を持っているか確認して開ける
If playerHasKey Then
' 扉を開けてクリア
MsgBox "クリア!"
Else
MsgBox "鍵が必要です。"
Case GridCell.Key
'鍵があるなら取得する
playerHasKey = True
MsgBox "鍵を手に入れた"
End If
End Select
' 移動先に移動する
playerX = newX
playerY = newY
End Sub
' 敵と戦う
Sub AttackEnemy()
' 敵にダメージを与える
' この部分は実装してください
End Sub
' アイテムを取得する
Sub PickupItem()
' アイテムの種類に応じて効果を適用する
' この部分は実装してください
End Sub
' ダメージを受ける
Sub TakeDamage(damage As Integer)
' ダメージを受けてHPを減らす
playerHP = playerHP - damage
If playerHP <= 0 Then
' HPが0以下になったらゲームオーバー
MsgBox "ゲームオーバー"
End If
End Sub
実は以下の図で言うところの「7」のこのままだと使えない処理ですが、全く役に立たないソースだったため削除しています。
そこはごっそり消しました。今時点だとあってもエラーの原因になるだけで何も役に立ちません。
Sub Init() を Private Sub Init()に修正
タイトルの通りなんですが、第三話で解説しているSub Init()(初期化処理のプロシージャ)のヘッダ部を変更しています。
このように直しておかないと、プロシージャからプロシージャへ移動する際に変数を引き継いでくれません。
そのため、ここは修正しています。
プレイヤーの「セル」の初期位置を指定
後、初期化処理の「キャラクターの初期位置を設定」部分に以下を追記しました。
' キャラクターの初期位置を設定
playerX = 1
playerY = 1
Sheet1.Cells(playerY, playerX).Activate
こんな感じですね。こうしないとゲーム開始時にフォーカスが初期位置(セル:A1)に移動してくれないので、追加しました。
セルに色を付ける処理の追加
後、移動したセルは別の色に変わらないとかなり微妙です。
そこでセルの移動処理の最後に以下のソースを足しました。
プレイヤーがいるセルを指定の色(35は黄緑)にするコードを以下に追記しました。
セルの移動処理が終わった直後に配置しています。
後、もう一行コードを追加します。
ゲームのリスタート時に元の色に戻したいですよね?
そのため、Init(初期化)の際にセルに数値をセットしているForループ分にもセルの色指定のコードを混ぜました。
これでゲームリスタート時に元のセルの色に戻してくれます。
これで敵やアイテムが出現しないもののクリアはできるゲームが完成しました。
RPGゲームをとりあえず動かしてみる
お待たせいたしました。第5話目にして初めてゲームを動かすことができます。
ということで、最後に少し設定をしてゲームで遊んでみましょう。
ゲームスタートボタンにマクロを登録する
第二話で作成しておいた「ゲームスタート」ボタンにマウスを移動させます。右クリックしてメニューが開いたら、「マクロの登録」を選択します。
①のマクロの部分に以下のように記入してください。
②「OK」ボタンを押下でマクロ登録完了です。
これによって、ゲームスタートをすると「Init(初期化処理)」を呼び出します。
- 10×10の配列にイベントをセットする
- 10×10のセルに青色を付ける
- 鍵と扉を配列に1つずつセットする
- ゲームプレイヤーを初期位置(1,1)に移動
- プレイヤーのHP10をセットする
- プレイヤーの鍵を非所持にする
- プレイヤーの攻撃力を1でセットする
ということで、初期化してゲームが開始できる状態にしてくれます。
因みに自分で設定するのすら面倒…という方は第5話までの内容を反映したエクセルを以下よりダウンロードできますのでよろしければお使いください。尚、怪しいことは一切していませんが、ダウンロードは自己責任でお願いいたします。
\ クリックでダウンロード /
さあ、VBA RPGゲームを遊んでみよう!
ということで、動画をとってみましたのでプレイシーンを見てみましょう
ブハハハッこれは酷い。
折角、セルにHPや鍵などのステータスがあっても変化しませんし、HPが0になってゲームオーバーでもゲーム続けられちゃうし。
まだまだ、楽しめるほどのゲームではありませんが、なんとなくInocchiQuestの片りんは感じてもらえたのではないでしょうか?
ソースがシンプルなので、手を加えられそうなところは是非弄ってみてください。
ということで今回はここまで。
次回は「攻撃する」、「アイテムを使う」を追加したいと思います。
残念パパことイノッチでした!
では、また
コメント
コメント一覧 (4件)
F*ckin’ tremendous things here. I’m very glad to look your post. Thank you a lot and i’m taking a look forward to touch you. Will you kindly drop me a e-mail?
I’d incessantly want to be update on new posts on this website , saved to bookmarks! .
Throughout this great pattern of things you secure an A with regard to effort. Exactly where you actually confused us was first in your specifics. As people say, the devil is in the details… And it couldn’t be much more true right here. Having said that, let me inform you just what did work. The article (parts of it) is actually incredibly engaging which is possibly the reason why I am taking an effort in order to comment. I do not really make it a regular habit of doing that. Secondly, whilst I can certainly notice the leaps in reason you make, I am not necessarily confident of just how you appear to unite your details which in turn help to make the final result. For right now I will subscribe to your position but trust in the near future you link your dots much better.
Wow that was strange. I just wrote an extremely long comment but after I clicked submit my comment didn’t show up. Grrrr… well I’m not writing all that over again. Anyhow, just wanted to say wonderful blog!