Excel(VBA)でカワイイゲームを作ろう!
こんにちは「つけらっとゲームス」プログラム担当のとちです。
今回は「ゲームを作ってみたいけど、どうしたら作れるの?」にお答えする記事のひとつで、且つ、以下の記事のパワーアップ版と言えるでしょう!
Unityなどのゲームエンジンを使うのは難しそう、もうちょっと馴染みのあるソフトを使ってゲーム作れないかなーっていう方にオススメです。
Excel使って簡単なゲームを作ってみましょう!
ちなみに、こんなゲームができます。
なお、この記事のスクショ等についてなんですが…
わたしのPCに入っているMicrosoft office Home and Business 2016でスクショを撮ったので、皆さんのお手元のExcelと微妙に異なる場合があります。
が、開発に使用するVBA(Microsoft Visual Basic for Applications)は同じで作業内容も変わりません。Microsoft365のExcelでも動作確認しました。
では、まず手始めに開発環境を整えましょう。
同テーマの前回記事「Excel(VBA)で簡単なゲームを作る」の「Excelの準備」を参照してVBAを使えるようにします。
開発環境は整いましたか?
そしたら先に進みましょう!
必要な素材を準備する
ゲームがカワイイ雰囲気になるか、カッコいい雰囲気になるかは、やっぱり画面に使用するグラフィックによって変わると思います。
というわけで、かわいい素材を集めるところから始めましょう。もちろん自分で作れる(描ける)方は、ご自分で用意して構いません。
今回のサンプルゲームはコチラのサイトからお借りしております。
やわらかく、かわいらしい素材がありますのでありがたいです!
DLしたものを羅列するとこんな感じ。
「ゲーム背景」「案内役の猫」「ふきだし」「感情アイコン2種」
感情アイコンは「勝ち」「負け or 引き分け」の2種類です。
サンプルゲームで使用した画像は多少の加工をしております。
ここに貼り付けると再配布になってしまうので、お手数をおかけしますがご自分でDLをお願いします。
別の画像をDLして自分好みに改造してもいいですね。
マルとバツについては、わたしが準備したモノを流用しても構いません。
またゲームに使用する素材のサイズも変更しておきましょう。
「ゲーム背景」 800 x 450 ピクセル
「案内役の猫」 120 x 120 ピクセル
「ふきだし」 260 x 210 ピクセル
「感情アイコン」どちらも 80 x 80 ピクセル
ここで少々問題が…Excel(VBA)で使用できる画像なのですが、png形式は使えません。jpeg形式に変換する必要があります。
先程のOKUMONOさんでDLした画像はpng形式…変換しましょう。
Photoshop、Gimpあたりの画像編集ソフトを使用できる方はそちらで編集していただいて構いません。「そんなの持ってないよ!」という方も安心。Windows付属のペイントでも十分可能です。
ペイントで画像ファイルを開きましょう。
ゲーム背景を例にします。そして以下の通り、順に進めてください。
これを繰り返し、他の素材も推奨サイズに変更しJPEG形式にします。
ユーザーフォームを作る
素材が揃ったらExcel側の作業をします。
まずは「挿入」>「ユーザーフォーム」でまっさらなユーザーフォームを準備しましょう。
次にユーザーフォームのプロパティを変更していきます。
(オブジェクト名):MaruBatsuForm
Caption:マルバツゲーム
Height:360
Picture:ゲーム背景の素材を選びます
Width:610
これ以外のプロパティの項目については特に触らなくても大丈夫なハズ。
色々触ってみると仕組みが解ってるくるので、自分なりに変更してみるのも勉強になりますよ!
次に、MaruBatsuFormを選んでツールボックスを表示します。
もし表示されなかった場合は下のスクリーンショットを見てください。
「表示」>「ツールボックス」を選ぶと表示されます。
バツを表示するマス目を作る
引き続きフォーム上にオブジェクトを設置していきます。
ツールボックスから「イメージ」を選んでユーザーフォーム上にマス目を作っていきます。9マス必要なので9個同じモノをつくりましょう。
このイメージオブジェクトに対してプロパティを設定していきます。
ここで特に重要なのがオブジェクト名です。
左上のイメージオブジェクトのプロパティを例にします。
(オブジェクト名):ImgB_1
BorderStyle:1 - fmBorderStyleSingle
Height:60
Picture:バツ印の画像
Width:60
左上を「1」として、隣を「2」、その隣を「3」
ひとつ下にいって左が「4」、隣を「5」、隣を「6」
さらに下にいって左が「7」、隣を「8」、隣を「9」とします。
各イメージオブジェクト名はそれに対応させます。オブジェクト名以外は上記で統一してください。
マルを表示するマス目を作る
それが終わったら今度はマルの分も作っていきます。
(オブジェクト名):ImgM_1
BorderStyle:1 - fmBorderStyleSingle
Height:60
Picture:マル印の画像
Width:60
これでマルとバツのイメージオブジェクトができました。
これらを全て選んで、プロパティを変更します。
同じ項目があるプロパティは、このように一括で変更が可能です。
Visible:True → False に変更します。
これで、このフォームを起動したら18個のイメージオブジェクトは見えない設定となります。今度は改めてマルのイメージオブジェクト9個を選択します。
これをバツのイメージオブジェクトの上に配置します。
ImgB_1 の上には ImgM_1 が、ImgB_9 の上には ImgM_9 が置かれます。
押下判定用に透明ラベルを作る
画面の右側が空きました。今度はラベルオブジェクトを作っていきます。
下のスクリーンショットの様にツールボックスからラベルを選び同じ大きさのラベルを9個作ります。
次はいま作ったラベルのプロパティを変更していきます。
左上のラベルを例にします。
(オブジェクト名):Mas_1
BackStyle:0 - fmBackStyleTransparent
BorderStyle:1 - fmBorderStyleSingle
Caption:消します(何も入っていない状態にします)
Height:60
Width:60
これで透明のラベルができるハズです。
大事なのがこれらのラベルのオブジェクト名です。
配置に合わせて名前を変更しておきます。
次にラベルオブジェクト9個を選んで、バツとマルのイメージオブジェクトの上に重ねて配置します。番号とオブジェクト名が対応する位置に配置してください。
その他のオブジェクトも配置する
他のオブジェクトも配置していきましょう。
「案内役の猫」「ふきだし」はイメージオブジェクトで作ります。
更に「ふきだし」の中に透明なラベルを配置しておきます。
ここにはゲーム中のメッセージを表示する予定です。
各オブジェクトのプロパティ例です。
まずは「案内役の猫」
(オブジェクト名):Image1
BackStyle:0 - fmBackStyleTransparent
BorderStyle:0 - fmBorderStyleNone
Height:96
Picture:案内役の猫を選択します。
Width:96
次は「ふきだし」
(オブジェクト名):Image2
BackStyle:0 - fmBackStyleTransparent
BorderStyle:0 - fmBorderStyleNone
Height:162
Picture:ふきだしの画像を選んでください。
Width:204
最後は「ゲームメッセージ」のラベルオブジェクトです。
これは「ふきだし」の中に納まる様に作っておきます。
(オブジェクト名):Msg
BackStyle:0 - fmBackStyleTransparent
BorderStyle:0 - fmBorderStyleNone
Caption:ここにメッセージを表示するよ
Font:ご自分の好みで変更してみてください!
枠線が気になる!
これまで作ってきた自分のユーザーフォームを見ましょう。
それっぽくなってきましたね。でも「マルバツ9マスの内側の線が太くて、外周が細いから気になる」って方もいますよね、きっと!
では、ラベルを作って外周の枠を太くしましょう。
いつも通り、ラベルを作ります。
(オブジェクト名):Mas_waku
BorderStyle:1 - fmBorderStyleSingle
Height:182
Picture:ふきだしの画像を選んでください。
Width:182
ただ、このオブジェクトを重ねるとラベルでマルバツが見えなくなってしまいます。そこで表示順を変更します。
このオブジェクトを選んでいる状態で上のメニューから
「書式」>「順序」>「最背面へ移動」を選ぶと各オブジェクトの奥に配置されるハズです。今後も画面の調整などに使うので覚えておくと便利です!
その他のオブジェクトも配置する2
ゲームが終わった後にどうするかを選択するボタンを2つ配置します。
スクリーンショットで言うとゲーム画面の右下の「もう1回!」「おわる」を追加します。これはツールボックスのコマンドボタンで作ります。
コマンドボタンはほぼデフォ設定ですが念のためプロパティ例です。
まずは「もう1回」のボタンです。
(オブジェクト名):CommandButton1
Caption:もう1回!
Font:お好みのフォントにしてくださいね!
次は「おわる」のボタンです。
(オブジェクト名):CommandButton2
Caption:おわる
Font:こちらも好きなフォントでいいです!
引き続き感情アイコンを配置します。
勝ち用のアイコンと、負け(引き分け)用のアイコン2つを用意して、あとで重ねます。どちらもイメージオブジェクトで作ります。
感情アイコン(勝)のプロパティ例です。
(オブジェクト名):Img_kati
BackStyle:0 - fmBackStyleTransparent
BorderStyle:0 - fmBorderStyleNone
Picture:勝ち用のアイコンを設定してください!
Visible:True → False に変更します。
感情アイコン(負)のプロパティ例です。
(オブジェクト名):Img_make
BackStyle:0 - fmBackStyleTransparent
BorderStyle:0 - fmBorderStyleNone
Picture:負け用のアイコンを設定してください!
Visible:True → False に変更します。
プロパティの設定が終わったら感情アイコンを重ねましょう。
これで長かったフォームにオブジェクトを配置する作業も終わりですが、バランスやオブジェクトの表示順が気になる場合は微調整をしましょう。
プログラムコードをコピペしよう!
あとはプログラムコードを書くだけです。実はそんなに長いプログラムではないので安心です。フォーム上にある何らかのオブジェクトをダブルクリックしてみてください。
こんな感じの画面が表示されると思います。
まずは、2行ほど書かれているコードを消しちゃいましょう。
そしたら、とりあえず現時点で中身の意味は気にしないで以下のコードを丸々コピペしましょう。
Option Explicit
Dim WinSW As Integer '【変数定義】勝者スイッチ [1]Player [2]Com [ 3]引き分け
Dim MbFlg(1 To 9) As Integer '【 〃 】マルバツフラグ [0]未選択 [1]マル [-1]バツ
Dim ImgBt(1 To 9) As Object '【 〃 】バツのイメージオブジェクト
Dim ImgMr(1 To 9) As Object '【 〃 】マルのイメージオブジェクト
Dim GmMsg(0 To 3) As String '【 〃 】ゲーム中に表示するメッセージ
'--------------------------------------------------------
' MaruBatsuForm 初期化
'--------------------------------------------------------
Private Sub UserForm_Initialize() '
'
Set ImgBt(1) = ImgB_1 '【OBJ設定】マス1 バツのイメージオブジェクト
Set ImgBt(2) = ImgB_2 '【 〃 】マス2 〃
Set ImgBt(3) = ImgB_3 '【 〃 】マス3 〃
Set ImgBt(4) = ImgB_4 '【 〃 】マス4 〃
Set ImgBt(5) = ImgB_5 '【 〃 】マス5 〃
Set ImgBt(6) = ImgB_6 '【 〃 】マス6 〃
Set ImgBt(7) = ImgB_7 '【 〃 】マス7 〃
Set ImgBt(8) = ImgB_8 '【 〃 】マス8 〃
Set ImgBt(9) = ImgB_9 '【 〃 】マス9 〃
'
Set ImgMr(1) = ImgM_1 '【OBJ設定】マス1 マルのイメージオブジェクト
Set ImgMr(2) = ImgM_2 '【 〃 】マス2 〃
Set ImgMr(3) = ImgM_3 '【 〃 】マス3 〃
Set ImgMr(4) = ImgM_4 '【 〃 】マス4 〃
Set ImgMr(5) = ImgM_5 '【 〃 】マス5 〃
Set ImgMr(6) = ImgM_6 '【 〃 】マス6 〃
Set ImgMr(7) = ImgM_7 '【 〃 】マス7 〃
Set ImgMr(8) = ImgM_8 '【 〃 】マス8 〃
Set ImgMr(9) = ImgM_9 '【 〃 】マス9 〃
'--
'-- ゲーム中のメッセージを設定
'--
GmMsg(0) = "キミは〇だよ! マスをクリック してね!"
GmMsg(1) = "キミの勝ちだよ!おめでとう!"
GmMsg(2) = "キミの負けだよ!残念でした!"
GmMsg(3) = "引き分けだね..."
'
Call GameStartProc 'ファンクション「ゲームスタート処理」
'
End Sub '
'--------------------------------------------------------
' ゲームスタート処理
'--------------------------------------------------------
Function GameStartProc() '
'
Dim ix As Integer '【変数定義】For文の添字
'
For ix = 1 To 9 '■ループ
MbFlg(ix) = 0 '├マルバツフラグの初期化
ImgBt(ix).Visible = False '├バツのイメージオブジェクト 非表示化
ImgMr(ix).Visible = False '├マルのイメージオブジェクト 非表示化
Next '└ループ終端
'
CommandButton1.Visible = False 'ボタン「もう1回!」非表示化
CommandButton2.Visible = False 'ボタン「おわる」 非表示化
Img_kati.Visible = False '感情アイコン(勝) 非表示化
Img_make.Visible = False '感情アイコン(負) 非表示化
'
WinSW = 0 '勝者スイッチの初期化
Msg.Caption = GmMsg(0) 'メッセージ変更
Randomize '乱数の初期化
'
End Function '
'--------------------------------------------------------
' マスをクリックした際の処理
'--------------------------------------------------------
Function Player_MasClick(wMas As Integer)
'
If MbFlg(wMas) <> 0 Then Exit Function '■クリックされたマスが「0」未選択以外だった場合 >> この処理を抜ける
If WinSW <> 0 Then Exit Function '■この時点で勝者スイッチが「0」以外だった場合 >> この処理を抜ける
'
MbFlg(wMas) = 1 'クリックされたマスが「1」マルにする
ImgMr(wMas).Visible = True 'クリックされたマスのマルオブジェクトを表示化
'
WinSW = 0 '勝者スイッチを初期化
Call GameSet_Hantei 'ファンクション ゲームセット判定
'
If WinSW = 0 Then Call Com_Proc '■勝者スイッチが「ゲームセット判定」後でも「0」だった場合 >> ファンクション Com処理
If WinSW > 0 Then Call GameSet_Taiou '■勝者スイッチが「ゲームセット判定」後でも「0」以外の場合 >> ファンクション ゲームセット後の対応
'
End Function '
'--------------------------------------------------------
' ゲームセット判定
'--------------------------------------------------------
Function GameSet_Hantei() '
'
Dim wHan(1 To 8) As Integer '【変数定義】終了判定フラグ
Dim ix As Integer '【変数定義】終了判定ループのIndex
'
wHan(1) = MbFlg(1) + MbFlg(2) + MbFlg(3) '横向き(上)の3マスのマルバツフラグ合計
wHan(2) = MbFlg(4) + MbFlg(5) + MbFlg(6) ' 〃 (中) 〃
wHan(3) = MbFlg(7) + MbFlg(8) + MbFlg(9) ' 〃 (下) 〃
wHan(4) = MbFlg(1) + MbFlg(4) + MbFlg(7) '縦向き(左) 〃
wHan(5) = MbFlg(2) + MbFlg(5) + MbFlg(8) ' 〃 (中) 〃
wHan(6) = MbFlg(3) + MbFlg(6) + MbFlg(9) ' 〃 (右) 〃
wHan(7) = MbFlg(1) + MbFlg(5) + MbFlg(9) '斜め(左上から右下)の3マスのマルバツフラグ合計
wHan(8) = MbFlg(3) + MbFlg(5) + MbFlg(7) '斜め(左下から右上) 〃
'
For ix = 1 To 8 '■ループ
If wHan(ix) = 3 Then WinSW = 1 '├◆マルバツフラグの合計が 3の場合 >> Playerの勝ち
If wHan(ix) = -3 Then WinSW = 2 '├◆マルバツフラグの合計が-3の場合 >> Comの勝ち
If WinSW <> 0 Then Exit For '├◆勝者スイッチが0以外の場合 >> ループを抜ける
Next '└ループ終端
'
End Function '
'--------------------------------------------------------
' ゲームセット後の対応
'--------------------------------------------------------
Function GameSet_Taiou() '
'
Msg.Caption = GmMsg(WinSW) '表示するメッセージの変更
CommandButton1.Visible = True 'ボタン「もう1回!」を表示化
CommandButton2.Visible = True 'ボタン「おわる」 を表示化
'
If WinSW = 1 Then Img_kati.Visible = True '■勝っている場合 >> 感情アイコン(勝)表示化
If WinSW > 1 Then Img_make.Visible = True '■負けか引き分け >> 感情アイコン(負)表示化
'
End Function '
'--------------------------------------------------------
' Com処理
'--------------------------------------------------------
Function Com_Proc() '
'
Dim ComIns As Integer '【変数定義】Comがバツを入れるマス目番号
Dim UseMas As Integer '【変数定義】マルかバツが入っているマス目数
ComIns = Int(9 * Rnd + 1) 'Comがバツを入れるマス目番号をランダムに取得
UseMas = 0 'マルかバツが入っているマス目数の初期化
'
Do While True '■ループ
If MbFlg(ComIns) = 0 Then '├◆Comが選んだマス目のマルバツフラグが[0]未選択 の場合
MbFlg(ComIns) = -1 '│├マルバツフラグを[-1]バツ にする
ImgBt(ComIns).Visible = True '│├バツのイメージオブジェクトを表示化する
Exit Do '│└ループを抜ける
End If '│
UseMas = UseMas + 1 '├マルかバツが入っているマス目数を+1
ComIns = ComIns + 1 '├ランダムで選択したマス目の次のマス目にする
If ComIns >= 10 Then ComIns = 1 '├◆ランダムで選択したマス目番号が10以上だった場合 >> 1に戻す
If UseMas >= 9 Then Exit Do '├◆マルかバツが入っているマス目数が9以上だった場合 >> ループを抜ける
Loop '└ループ終端
'
WinSW = 0 '勝者スイッチを初期化
If UseMas >= 9 Then WinSW = 3 '■マルかバツが入っているマス目数が9以上だった場合 >> 勝者スイッチ[3]引き分け
Call GameSet_Hantei 'ファンクション ゲームセット判定
'
End Function '
'--------------------------------------------------------
' ボタン「もう1回!」をクリック
'--------------------------------------------------------
Private Sub CommandButton1_Click() '
Call GameStartProc ' ファンクション「ゲームスタート処理」
End Sub '
'--------------------------------------------------------
' ボタン「おわる」をクリック
'--------------------------------------------------------
Private Sub CommandButton2_Click() '
End ' ゲームの終了
End Sub '
'--------------------------------------------------------
' 以下 それぞれのマス目をクリック
'--------------------------------------------------------
Private Sub Mas_1_Click()
Player_MasClick (1)
End Sub
Private Sub Mas_2_Click()
Player_MasClick (2)
End Sub
Private Sub Mas_3_Click()
Player_MasClick (3)
End Sub
Private Sub Mas_4_Click()
Player_MasClick (4)
End Sub
Private Sub Mas_5_Click()
Player_MasClick (5)
End Sub
Private Sub Mas_6_Click()
Player_MasClick (6)
End Sub
Private Sub Mas_7_Click()
Player_MasClick (7)
End Sub
Private Sub Mas_8_Click()
Player_MasClick (8)
End Sub
Private Sub Mas_9_Click()
Player_MasClick (9)
End Sub
ゲームを動かしてみよう!
先程のプログラムコードをコピペし終わったら実際にゲームを動かしてみましょう。
フォーム「MaruBatsuForm」をダブルクリックしてフォームを表示したら、
画面上側の再生ボタンをクリックするとプログラムが動き出します。
上手く動かない場合は、同テーマの前回記事「Excel(VBA)で簡単なゲームを作る」の「動かないんだけど!?(怒)」を参考に原因を探ってみましょう。落ち着いて確認してみてください。
動かしてみて思うことは?
自分で作ったゲーム。単純なマルバツゲームではありますが苦労して作ると、愛おしいゲームだと感じませんか?
ただ、何度かプレイしてると気になる点が出てくると思います。
「このゲームの対戦相手(Com)ってバカなのでは?」
そうなんです、先程のプログラムコードでは空いているマスにランダムにバツを置く動きをするComなので…正直言ってすごく弱いんです。
それに、たったひとつの画面で動きも特にないため、ゲームっぽくありません。せめてタイトル画面があってゲーム画面に遷移するとか、そういう仕組みが欲しいですね。
もっと言えば、Excelファイルを開いたら自動でゲームが動くとか…
プログラムコードもコピペしただけなので、何をしているか理解できないかもしれません。
もうちょっと手を入れたら、もうちょっとマシなゲームになりそうです。
というわけで、次回は「応用編」として以下の内容を取り扱う予定です。
・対戦相手の強化
・タイトル画面からの画面遷移
・Excelファイルを開いたらゲーム起動
・プログラムコード解説
今回は全般的に作業でしたが次回は勉強っぽい有料記事になります。
書いてる途中で「授業やワークショップで使える内容だわ…」と感じたので、続きが気になる方は是非読んでください。
(※ 記事が完成したら公開します。少々お待ちください。)公開しました!
「ゲームを作ってみたいけど、どうしたら作れるの?」にお答えする記事は他にもありますので、ご興味がございましたら下記の関連記事もご覧ください。
(↓)アナログなゲームを作ってみてもいいんじゃない?っていう記事
(↓)ゲームブックを作ったので試遊だけでもいかが?っていう記事
(↓)クォリティはともかくカードゲームも作ってみたよって記事
(↓)アルゴリズムやフローチャートなど情報の勉強関連は以下のマガジンをご覧ください!
長い記事を最後まで読んでくださりありがとうございます。
今日はここまでです。お疲れ様でした~。