タイトル画面を表示する
タイトル画面を表示する
デバッグすると実行ファイル(bin¥debug¥net10.0-windows¥colorVBForms.exe)が書き出されます。そこからの相対パスで「Title.png」画像を読み込みます。「title」メソッドでゲーム状態をタイトル画面にし、マウスが押されたら「onClick2Start」関数を呼び出します。この関数ではマウスが押された時のトリガーを解除し、「init」関数でゲーム状態をメインループにします。図2のようにタイトル画面では中央にタイトル画像を表示します。
ところで、先に「Go」言語で解説した際、プロパティやメソッドの頭文字をprivateは小文字、publicは大文字にしたので、C#やVisual Basic.NETでも同様にしました。ただし、C#やVB.NETではメソッド名の頭文字はアクセス修飾子に関わらず大文字にするのが一般的なようです。
・サンプルコード「Forms1.vb」ファイル
Imports System.Drawing
Imports System.Runtime.Intrinsics
Imports System.Windows.Forms
Partial Public Class Form1
Inherits Form
Private img(3) As Image
Enum GAME_STATE
TITLE
MAIN_LOOP
GAME_OVER
STAGE_CLEAR
End Enum
Private gameState As GAME_STATE
Public Sub New()
InitializeComponent()
Me.DoubleBuffered = True ' チラつき防止
' 画像読み込み
img(3) = Image.FromFile("../../../images/Title.png")
title()
End Sub
Private Sub title()
gameState = GAME_STATE.TITLE
AddHandler Me.MouseDown, AddressOf onClick2Start
End Sub
Private Sub onClick2Start(sender As Object, e As MouseEventArgs)
RemoveHandler Me.MouseDown, AddressOf onClick2Start
init()
End Sub
Private Sub init()
gameState = GAME_STATE.MAIN_LOOP
End Sub
Protected Overrides Sub OnPaint(e As PaintEventArgs)
MyBase.OnPaint(e)
Select Case gameState
Case GAME_STATE.TITLE
Dim x As Integer = Me.ClientSize.Width \ 2 - img(3).Width \ 4
Dim y As Integer = Me.ClientSize.Height \ 2 - img(3).Height \ 4
e.Graphics.DrawImage(img(3), x, y)
End Select
End Sub
End Class【サンプルコードの解説】
「Form1」コンストラクタでタイトル画像をimg(3)プロパティに読み込みます。
「title」メソッドでゲーム状態を「GAME_STATE.TITLE」にし、マウスが押されたら「onClick2Start」メソッドをトリガーします。
onClick2Startメソッドでマウスが押された時のトリガーを解除します。
「init」メソッドでゲーム状態を「GAME_STATE.MAIN_LOOP」にします。
「OnPaint」メソッドでタイトル画面で画像を表示します。
色ブロックを表示する
「Sprite.vb」ファイルをcolorVBFormsフォルダ内に「Add」→「New Item」メニューで新規作成します。タイトル画面でマウスを押したらゲーム画面に遷移し、色ブロックが複数表示されて移動し、画面外に出たら削除されましたね(図3)。
・サンプルコード「Sprite.vb」ファイル
Imports System.Drawing
Imports System.Windows.Forms
Public Class Sprite
Public X As Single
Public Y As Single
Public VX As Single
Public VY As Single
Public Img As Image
Public Col As Integer
Private rand As New Random()
Public Sub New(clientSize As Size, img() As Image, col As Integer)
X = rand.Next(0, clientSize.Width)
Y = rand.Next(0, clientSize.Height)
VX = rand.Next(-4, 4)
VY = rand.Next(-4, 4)
Me.Col = col
Me.Img = img(col)
End Sub
Public Function Update(clientSize As Size) As Boolean
X += VX
Y += VY
' 画面外なら削除
If X > clientSize.Width OrElse
Y > clientSize.Height OrElse
X + Img.Width < 0 OrElse
Y + Img.Height < 0 Then
Return True
End If
Return False
End Function
End Class【サンプルコードの解説】
「Sprite」クラスで色ブロック1個ずつの座標(X,Y)プロパティ、移動量(VX,VY)プロパティ、色「Col」プロパティ、画像データ「Img」プロパティ、乱数「rand」プロパティを宣言します。
Spriteクラスの「New」コンストラクタでランダムな座標、移動量、ブロックの色、画像をセットします。
「Update」メソッドで色ブロックを移動し、画面外に出たらTrueを戻り値で返します。そうでなければFalseを返します。
・サンプルコード「Forms1.vb」ファイル
Imports System.Drawing
Imports System.Runtime.Intrinsics
Imports System.Windows.Forms
Partial Public Class Form1
Inherits Form
Private timer As New Timer()
Private sprites As New List(Of Sprite)()
Private rand As New Random()
Private img(3) As Image
Private stage As Integer = 2
Enum GAME_STATE
TITLE
MAIN_LOOP
GAME_OVER
STAGE_CLEAR
End Enum
Private gameState As GAME_STATE
Public Sub New()
InitializeComponent()
Me.DoubleBuffered = True ' チラつき防止
' 画像読み込み
img(0) = Image.FromFile("../../../images/0.png")
img(1) = Image.FromFile("../../../images/1.png")
img(2) = Image.FromFile("../../../images/2.png")
img(3) = Image.FromFile("../../../images/Title.png")
title()
End Sub
Private Sub title()
gameState = GAME_STATE.TITLE
RemoveHandler timer.Tick, AddressOf update
timer.Stop()
RemoveHandler Me.MouseDown, AddressOf onMouseDown
AddHandler Me.MouseDown, AddressOf onClick2Start
End Sub
Private Sub onClick2Start(sender As Object, e As MouseEventArgs)
RemoveHandler Me.MouseDown, AddressOf onClick2Start
init()
' タイマー(10fps)
timer.Interval = 100
AddHandler timer.Tick, AddressOf update
timer.Start()
AddHandler Me.MouseDown, AddressOf onMouseDown
End Sub
Private Sub init()
gameState = GAME_STATE.MAIN_LOOP
sprites.Clear()
' 初期生成
For i As Integer = 0 To stage * 3 - 1
sprites.Add(New Sprite(Me.ClientSize, img, i Mod 3))
Next
End Sub
Private Sub update(sender As Object, e As EventArgs)
For i As Integer = sprites.Count - 1 To 0 Step -1
If sprites(i).Update(Me.ClientSize) Then
sprites.RemoveAt(i)
End If
Next
Me.Invalidate() ' 再描画
End Sub
Protected Overrides Sub OnPaint(e As PaintEventArgs)
MyBase.OnPaint(e)
Select Case gameState
Case GAME_STATE.TITLE
Dim x As Integer = Me.ClientSize.Width \ 2 - img(3).Width \ 4
Dim y As Integer = Me.ClientSize.Height \ 2 - img(3).Height \ 4
e.Graphics.DrawImage(img(3), x, y)
Case GAME_STATE.MAIN_LOOP
For Each s As Sprite In sprites
e.Graphics.DrawImage(s.Img, s.X, s.Y)
Next
End Select
End Sub
Private Sub onMouseDown(sender As Object, e As MouseEventArgs)
End Sub
End Class【サンプルコードの解説】
Form1クラスで「sprites」プロパティをSpriteクラスのリストとして宣言します。
img(0)~img(2)に赤緑青の色ブロックの画像を読み込んでインスタンスを代入します。
onClick2Startメソッドでタイマー(Timerクラス)を使って100ミリ秒ごと(10FPS)にupdateメソッドを呼び出します。titleメソッドではそれらを停止し、マウスが押された時の処理のトリガーを付け替えます。
「init」メソッドで、Spriteクラスのインスタンスとして色ブロックをstageの数値の3倍(3色分)追加します。
updateメソッドで色ブロックを移動し、画面外で削除し、再描画します。
OnPaintメソッドでゲーム状態がメインループ時、色ブロックを表示します。
大西拓磨さんという芸術家が「人と面白くコミュニケーションできないから、面白いものを作るしかない。アートは最後の砦」みたいに言っていました。まさに筆者もそんな感じです。
この記事をシェアしてください
