如何在VB.NET中动态添加和操作多个唯一的图片框?

时间:2019-07-06 08:44:27

标签: vb.net dynamic

我是一名高中生,正在做评估的基本游戏。 该游戏使棒球在玩家的屏幕上飞过,然后球员将其击退。

所有棒球都包含在图片框中,我需要能够制作无数个可以在运行时单独引用和移动的棒球。

我目前正在将图片框添加并存储在字典中。但是,每当我创建一个新的图片框并将其添加到表单中时,它就会覆盖该表单上以前创建的所有图片框。

我需要找到允许以前创建的图片框在创建新图片框时保留在窗体上的代码。

对于上下文,我在下面添加了程序的逻辑流程。

当前程序逻辑

Sub,它随机确定球是在屏幕的左侧,右侧,北侧还是南侧生成。

基于上述结果,可以通过更改空白变量来设置新的“棒球”图片框。

Sub,它将其作为“值”添加到字典中,而“键”具有一个名为ballNameNumber的变量。 同时,使用key ballNameNumber将随机数设置为名为ballVelocity的字典的Value。乘以一个称为关卡的变量,该变量随游戏时间的增加而增加。

因此,在这一点上,已经创建了一个球,在3个字典中具有相同的键名,每个字典都存储其图片框值和速度。

从4个生成位置中随机选择一个的子对象,根据该值将球的方向记录到名为ballDirection的字典中,然后在该位置创建球。

所有这些子项在名为tmrGameTime(间隔500)的计时器的每次计时中按此顺序发生,格式为frmGame(大小700,700)

  'Dictionaries used to log and describe the movement of the balls onscreen.
Dim spawnedBalls As Dictionary(Of Integer, PictureBox) = New Dictionary(Of Integer, PictureBox)
Dim ballVelocity As Dictionary(Of Integer, Integer) = New Dictionary(Of Integer, Integer)
Dim ballDirection As Dictionary(Of Integer, String) = New Dictionary(Of Integer, String)

'Variables used in the composition of dictionaries.
Dim ballNameNumber As Integer = 1
Dim numberOfBalls As Integer = 0
Dim level As Integer = 1
Dim ball As New Picturebox

'Turns on the game timer
Private Sub frmGame_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    tmrGameTime.Enabled = True
    tmrGameTime.Start()
End Sub

'Sets values to the ball variable (must be done within a sub otherwise an error is dispayed)
Public Sub ballSetUpLeft(ByRef ballTemplate)
    ballTemplate.SizeMode = PictureBoxSizeMode.StretchImage
    ballTemplate.Width = 34
    ballTemplate.Height = 29
    ballTemplate.Top = 325
    ballTemplate.Left = 55
    ballTemplate.Image = My.Resources.Baseball_Sprite
End Sub

Public Sub ballSetUpRight(ByRef ballTemplate)
    ballTemplate.SizeMode = PictureBoxSizeMode.StretchImage
    ballTemplate.Width = 34
    ballTemplate.Height = 29
    ballTemplate.Top = 325
    ballTemplate.Left = 593
    ballTemplate.Image = My.Resources.Baseball_Sprite
End Sub

Public Sub ballSetUpTop(ByRef ballTemplate)
    ballTemplate.SizeMode = PictureBoxSizeMode.StretchImage
    ballTemplate.Width = 34
    ballTemplate.Height = 29
    ballTemplate.Top = 59
    ballTemplate.Left = 333
    ballTemplate.Image = My.Resources.Baseball_Sprite
End Sub

Public Sub ballSetUpBottom(ByRef ballTemplate)
    ballTemplate.SizeMode = PictureBoxSizeMode.StretchImage
    ballTemplate.Width = 34
    ballTemplate.Height = 29
    ballTemplate.Top = 574
    ballTemplate.Left = 333
    ballTemplate.Image = My.Resources.Baseball_Sprite
End Sub


'Generates a random speed for a spawned ball based on the level value.
Public Function generateBallSpeed(ByVal level) As Integer

    Randomize()
    Dim ans As Integer = (((Rnd() * 10) * level) + 1)
    Return ans

End Function


'Logs the ball data into dictionaries
Public Sub createBall(ByRef spawnedBalls, ByRef ballVelocity, ByRef ballNameNumber, ByRef numberOfBalls, ByRef ballTemplate)

    'Adds a new ball with name and ballTemplate values to the dictionary.
    spawnedBalls.Add(ballNameNumber, ballTemplate)

    Dim v As Integer = generateBallSpeed(level)
    'Using the matching name, adds a velocity value to the ball
    ballVelocity.Add(ballNameNumber, v)

End Sub


'Spawns ball at a specific location on the form.
Public Sub spawnBallAtPitcher()

    Randomize()
    Dim pitcher As Integer = Int((4 - 1 + 1) * Rnd() + 1)
    Select Case pitcher
        Case 1
            Call ballSetUpLeft(ballTemplate)
            Call createBall(spawnedBalls, ballVelocity, ballNameNumber, numberOfBalls, ballTemplate)
            ballDirection.Add(ballNameNumber, "Left")
            ballNameNumber += 1
            Me.Controls.Add(spawnedBalls.Item(ballNameNumber - 1))

        Case 2
            Call ballSetUpRight(ballTemplate)
            Call createBall(spawnedBalls, ballVelocity, ballNameNumber, numberOfBalls, ballTemplate)
            ballDirection.Add(ballNameNumber, "Right")
            ballNameNumber += 1
            Me.Controls.Add(spawnedBalls.Item(ballNameNumber - 1))

        Case 3
            Call ballSetUpTop(ballTemplate)
            Call createBall(spawnedBalls, ballVelocity, ballNameNumber, numberOfBalls, ballTemplate)
            ballDirection.Add(ballNameNumber, "Top")
            ballNameNumber += 1
            Me.Controls.Add(spawnedBalls.Item(ballNameNumber - 1))

        Case 4
            Call ballSetUpBottom(ballTemplate)
            Call createBall(spawnedBalls, ballVelocity, ballNameNumber, numberOfBalls, ballTemplate)
            ballDirection.Add(ballNameNumber, "Down")
            ballNameNumber += 1
            Me.Controls.Add(spawnedBalls.Item(ballNameNumber - 1))

    End Select
End Sub

'Repeatedly spawns balls
Private Sub tmrGameTime_Tick_1(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles tmrGameTime.Tick
    Call spawnBallAtPitcher()
End Sub

结束班级

我希望这些图片框会以随机顺序出现在我的窗体上,直到四个在不同点可见(因为其他图片框会在前一个顶部创建)。但是,将创建on picturebox,然后在生成位置之间跳转。没有收到错误消息。

1 个答案:

答案 0 :(得分:0)

您的问题是您在代码中仅使用1个参考球。因此,每次要创建另一个球时,都可以使用新球替换前一个球。将4个过程中的代码更改为函数,然后返回新球。

'Sets values to the ball variable (must be done within a sub otherwise an error is dispayed)
Public Function ballSetUpLeft() As PictureBox
    Dim newBall As New PictureBox
    newBall.SizeMode = PictureBoxSizeMode.StretchImage
    newBall.Width = 34
    newBall.Height = 29
    newBall.Top = 325
    newBall.Left = 55
    newBall.Image = My.Resources.Baseball_Sprite
    Return newBall
End Function

Public Function ballSetUpRight() As PictureBox
    Dim newBall As New PictureBox
    newBall.SizeMode = PictureBoxSizeMode.StretchImage
    newBall.Width = 34
    newBall.Height = 29
    newBall.Top = 325
    newBall.Left = 593
    newBall.Image = My.Resources.Baseball_Sprite
    Return newBall
End Function

Public Function ballSetUpTop() As PictureBox
    Dim newBall As New PictureBox
    newBall.SizeMode = PictureBoxSizeMode.StretchImage
    newBall.Width = 34
    newBall.Height = 29
    newBall.Top = 59
    newBall.Left = 333
    newBall.Image = My.Resources.Baseball_Sprite
    Return newBall
End Function

Public Function ballSetUpBottom() As PictureBox
    Dim newBall As New PictureBox
    newBall.SizeMode = PictureBoxSizeMode.StretchImage
    newBall.Width = 34
    newBall.Height = 29
    newBall.Top = 574
    newBall.Left = 333
    newBall.Image = My.Resources.Baseball_Sprite
    Return newBall
End Function

然后更改调用函数的方式(以前是过程),如下所示:

Select Case pitcher
    Case 1
        Dim newBall = ballSetUpLeft()
        Call createBall(spawnedBalls, ballVelocity, ballNameNumber, numberOfBalls, newBall)
        ballDirection.Add(ballNameNumber, "Left")
        ballNameNumber += 1
        Me.Controls.Add(spawnedBalls.Item(ballNameNumber - 1))

    Case 2
        Dim newBall = ballSetUpRight()
        Call createBall(spawnedBalls, ballVelocity, ballNameNumber, numberOfBalls, newBall)
        ballDirection.Add(ballNameNumber, "Right")
        ballNameNumber += 1
        Me.Controls.Add(spawnedBalls.Item(ballNameNumber - 1))

    Case 3
        Dim newBall = ballSetUpTop()
        Call createBall(spawnedBalls, ballVelocity, ballNameNumber, numberOfBalls, newBall)
        ballDirection.Add(ballNameNumber, "Top")
        ballNameNumber += 1
        Me.Controls.Add(spawnedBalls.Item(ballNameNumber - 1))

    Case 4
        Dim newBall = ballSetUpBottom()
        Call createBall(spawnedBalls, ballVelocity, ballNameNumber, numberOfBalls, newBall)
        ballDirection.Add(ballNameNumber, "Down")
        ballNameNumber += 1
        Me.Controls.Add(spawnedBalls.Item(ballNameNumber - 1))

End Select

现在,您每次要创建另一个球都不会替换您的球。我离开了要给球设置动画并在投手击中球时移走球的任务。

我试图减少您代码中的冗余。这3个词典由一个单独的词典代替,该词典保存了球的信息(id,方向,速度和图片)。使用枚举而不是硬编码的数字作为方向。使用Random类而不是Randomize()和Rnd()函数。

Public Class frmGame
    'Dictionaries used to log and describe the movement of the balls onscreen.
    Private balls = New Dictionary(Of Integer, Ball)

    'Variables used in the composition of dictionaries.
    Private random As New Random
    Private lastBallID As Integer
    Private Const level As Integer = 1

    Private Sub frmGame_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        'Turns on the game timer
        tmrGameTime.Enabled = True
        tmrGameTime.Start()
    End Sub

    Private Sub tmrGameTime_Tick_1(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles tmrGameTime.Tick
        'Repeatedly spawns balls
        spawnBallAtPitcher()
    End Sub

    'Spawns ball at a specific location on the form.
    Private Sub spawnBallAtPitcher()

        lastBallID += 1
        Dim pitcher As Direction = random.Next(4) + 1
        Dim newBall = createBall(lastBallID, pitcher, random)
        Controls.Add(newBall.Picture)

        'Logs the ball data into dictionaries
        balls.Add(lastBallID, newBall)

    End Sub

    'Create new ball, set its ID, direction, velocity and picture
    Private Function createBall(ballID As Integer, direction As Direction, rnd As Random) As Ball

        Return New Ball With {
            .BallID = ballID,
            .Direction = direction,
            .Velocity = generateBallSpeed(level, rnd),
            .Picture = generateBallPicture(direction)
        }

    End Function

    'Generates a random speed for a spawned ball based on the level value.
    Private Function generateBallSpeed(ByVal level As Integer, ByVal rnd As Random) As Integer

        Return (rnd.Next(10) + 1) * level

    End Function

    'Generates a new picture of ball
    Private Function generateBallPicture(direction As Direction) As PictureBox

        Dim location = generatePictureLocation(direction)

        Return New PictureBox With {
            .SizeMode = PictureBoxSizeMode.StretchImage,
            .Width = 34,
            .Height = 29,
            .Top = location.Y,
            .Left = location.X,
            .Image = My.Resources.Baseball_Sprite
        }

    End Function

    'Generates a location for new picture of ball
    Private Function generatePictureLocation(direction As Direction) As Point

        Select Case direction
            Case Direction.Left
                Return New Point(55, 325)
            Case Direction.Right
                Return New Point(593, 325)
            Case Direction.Top
                Return New Point(333, 59)
            Case Direction.Bottom
                Return New Point(333, 574)
        End Select

    End Function

End Class

Public Enum Direction
    Left = 1
    Right
    Top
    Bottom
End Enum

Public Class Ball

    Public Property BallID As Integer
    Public Property Velocity As Integer
    Public Property Direction As Integer
    Public Property Picture As PictureBox

End Class