ゲーム実装で身に付くプログラミング 第13回

色ブロックを描画する

色ブロックを描画する

「colorVbWPF」プロジェクトを右クリックして表示されるメニューから「Add」→「New Item...」を選び、「ColorBlock.vb」ファイルを新規作成して追加します。

色ブロックは「ColorBlock」クラスで設計図を書きます。「New」コンストラクタで色ブロックを準備し、「GetImg」関数で画像をファイルから読み込みます(図2)。「Sub」プロシージャは戻り値を返さないメソッドで「Function」プロシージャは戻り値を返すメソッドです。

図2:色ブロックを描画

・サンプルコード「ColorBlock.vb」ファイル

Public Class ColorBlock

    Private x, y As Integer
    Private vx, vy As Integer
    Private img As Image
    Private color As Integer
    Private Shared ReadOnly rnd As New Random()
    Private parent As MainWindow

    Public Sub New(imageCanvas As Canvas, col As Integer, p As MainWindow)
        parent = p
        color = col
        img = GetImg(col)
        AddHandler img.MouseLeftButtonDown, AddressOf Img_MouseLeftButtonDown
        imageCanvas.Children.Add(img)
        x = rnd.Next(0, 1700)
        y = rnd.Next(0, 800)
        vx = rnd.Next(-3, 4)
        vy = rnd.Next(-3, 4)
        Canvas.SetLeft(img, x)
        Canvas.SetTop(img, y)
    End Sub

    Private Function GetImg(col As Integer) As Image
        Dim path As String = System.IO.Path.Combine(
            AppDomain.CurrentDomain.BaseDirectory,
            "../../../images",
            $"{col}.png"
        )
        Dim bitmap As New BitmapImage()
        bitmap.BeginInit()
        bitmap.UriSource = New Uri(path, UriKind.Absolute)
        bitmap.CacheOption = BitmapCacheOption.OnLoad
        bitmap.EndInit()
        bitmap.Freeze()
        ' Imageを作成
        Return New Image With {
                .Width = 100,
                .Height = 100,
                .Stretch = Stretch.Uniform,
                .Source = bitmap
            }
    End Function

    Private Sub Img_MouseLeftButtonDown(sender As Object, e As MouseButtonEventArgs)
    End Sub
End Class

【サンプルコードの解説】
ColorBlockクラスで色ブロックの位置(x,y)、移動量(vx,vy)、画像(img)、色(color)、乱数(rnd)、MainWindowクラス自体のインスタンス(parent)を宣言します。
NewコンストラクタでMainWindowクラスのインスタンスと色ブロックの色をセットし、「GetImg」メソッドでcolインデックスの色ブロック画像を読み込みます。色ブロックが左クリックされた時のイベントハンドラをセットし、「ImageCanvas」の子要素に色ブロックを追加します。ランダムに(x,y)と(vx,vy)を決め、imgのあるCanvasにx(SetLeft)、y(SetTop)の位置で配置します。
「GetImg」メソッドは、アプリのexeファイルを書き出したディレクトリからの相対パスで0.png~2.pngの画像をBitmapImageに読み込み、Imageクラスのインスタンスを生成して戻り値として返します。
「Img_MouseLeftButtonDown」は色ブロックがクリックが押された時に呼ばれます。

・サンプルコード「MainWindow.xaml.vb」ファイル

Class MainWindow
    Property colors As List(Of ColorBlock) = New List(Of ColorBlock)()
    Private WithEvents timer As New DispatcherTimer()
    Private stage As Integer = 2

    Public Sub New()
        InitializeComponent()
    End Sub

    Private Sub Title_MouseLeftButtonUp(sender As Object, e As MouseButtonEventArgs)
        TitleGrid.Visibility = Visibility.Hidden
        ImageCanvas.Visibility = Visibility.Visible
        Init()
    End Sub

    Private Sub Init()
        ImageCanvas.Children.Clear()
        colors.Clear()
        For i As Integer = 0 To stage * 3 - 1
            colors.Add(New ColorBlock(ImageCanvas, i Mod 3, Me))
        Next
    End Sub
End Class

【サンプルコードの解説】
MainWindowクラスで、「colors」リスト配列に色ブロックを、定期的に呼び出すタイマーを「timer」プロパティに、ステージ(面)の初期値として2を「stage」プロパティにセットします。
「Title_MouseLeftButtonUp」で、タイトル画像のマウスクリックが離されたらタイトルGridを隠してImageCanvasを表示し、「Init」メソッドを呼び出します。
Initメソッドで、ImageCanvasとcolorsをクリアし、colorsにstage×3色(R・G・B)の個数だけ色ブロックを追加します。

色ブロックを移動しゲームオーバーを処理する

今度は色ブロックを20FPSで毎フレーム更新して移動させます。すべての色ブロックが画面外に出たらflgが0になり、ゲームオーバー処理としてタイマーを停止し、タイトルGridを表示してImageCanvasを隠します。ゲームオーバー画面とサウンドは省略しました。

・サンプルコード「ColorBlock.vb」ファイル

Public Class ColorBlock
(中略)
    Public Sub New(imageCanvas As Canvas, col As Integer, p As MainWindow)
(中略)
    End Sub

    Private Function GetImg(col As Integer) As Image
(中略)
    End Function

    Public Function Update() As Integer
        x += vx
        y += vy
        Canvas.SetLeft(img, x)
        Canvas.SetTop(img, y)
        If x >= -100 And x <= 1800 And y >= -100 And y <= 900 Then
            Return 1
        End If
        Return 0
    End Function

    Private Sub Img_MouseLeftButtonDown(sender As Object, e As MouseButtonEventArgs)
    End Sub
End Class

【サンプルコードの解説】
「Update」メソッドで色ブロックの位置を移動量だけ移動します。

・サンプルコード「MainWindow.xaml.vb」ファイル

Imports System.Windows.Threading

Class MainWindow
(中略)
    Public Sub New()
        InitializeComponent()
    End Sub

    Private Sub Window_Loaded(sender As Object, e As RoutedEventArgs) Handles Me.Loaded
        timer.Interval = TimeSpan.FromMilliseconds(50)
    End Sub

    Private Sub Title_MouseLeftButtonUp(sender As Object, e As MouseButtonEventArgs)
        TitleGrid.Visibility = Visibility.Hidden
        ImageCanvas.Visibility = Visibility.Visible
        Init()
        timer.Start()
    End Sub

    Private Sub Init()
(中略)
    End Sub

    Private Sub Timer_Tick(sender As Object, e As EventArgs) Handles timer.Tick
        Dim flg As Integer = 0
        For Each col In colors
            flg += col.Update()
        Next
        If flg = 0 Then
            timer.Stop()
            TitleGrid.Visibility = Visibility.Visible
            ImageCanvas.Visibility = Visibility.Hidden
        End If
    End Sub
End Class

【サンプルコードの解説】
MainWindowクラスでウィンドウの読み込みが完了すると「Window_Loaded」メソッドが呼ばれ、タイマーを50ミリ秒ごとに更新(20FPS)します。
Title_MouseLeftButtonUpメソッドでタイマーをスタートします。
「Timer_Tick」メソッドで色ブロックを移動し、画面内にいたら1ずつ加算します。色ブロックが0個(flg = 0)ならタイマーをストップしてタイトル画面を表示し、ImageCanvasを隠します。

【コラム】イシュー度

イシュー度、つまり「問題にするほど価値がある題材かが重要だ」と気付かされました。解決策を考えてもイシュー度が低ければ無意味。売れないのに絵本のアイデアを考えているより、絵本以外を見つけるべきかと考えさせられました。

人気記事トップ10

人気記事ランキングをもっと見る

企画広告も役立つ情報バッチリ! Sponsored