图片框移动不同步

Picturebox movement out of sync

背景:我正在尝试用 Visual Basic 制作一个 Flappy Bird 风格的游戏来熟悉这门语言(我将需要在接下来的 2 年里用它编写代码,我真的不知道做出选择)。

问题出在管道的连续移动上。管道每 1200 毫秒生成一次。游戏检查每个标记为 "pipe""score" 的控件,并根据另一个间隔为 60 毫秒的计时器移动它。 gameloop 计时器的代码:

    Private Sub gameloop_Tick(sender As Object, e As EventArgs) Handles gameloop.Tick
        ' continuous movements
        player.Top += 10
        For Each c As Control In Controls
            If c.Tag = "pipe" Or c.Tag = "score" Then
                If c.Left < -40 Then ' checking if it's off screen, then removing it if so
                    Controls.Remove(c)
                Else ' if it's on screen, move it towards the player
                    c.Left -= 10
                End If
            End If
            If c.Tag = "collider" Or c.Tag = "pipe" Then ' checking for collision
                If player.Bounds.IntersectsWith(c.Bounds) Then
                    resetgame()
                End If
            End If
            If c.Tag = "score" Then ' scoring if player goes between
                If player.Bounds.IntersectsWith(c.Bounds) Then
                    Controls.Remove(c)
                    score += 1
                    scorelabel.Text = "Score: " & score
                End If
            End If
        Next
    End Sub

底部管道和得分区都同步移动,但顶部管道似乎落后一点(所有 3 个应该一起移动),并且随着比赛的进行逐渐变得更糟,see here. 为了清晰起见,得分区被设为粉红色。

我不确定是什么导致了这个问题。我检查了 gamelooppipegen 计时器的运行时间,两者的代码在计时器间隔内执行良好。我也尝试用 case 语句替换逻辑,但它仍然没有改变去同步化。我个人在网上找不到与此相关的任何内容。这是图片框的问题,VB 还是我犯了一个愚蠢的错误(这完全有可能,我对这种语言很陌生)。

Here's the full code on pastebin.

谢谢!

我在代码中犯的主要错误是在循环遍历数组时从数组中删除。相反,我制作了一个要删除的控件列表,然后循环遍历它:

    ' game logic
    Private Sub gameloop_Tick(sender As Object, e As EventArgs) Handles gameloop.Tick
        ' list of things to remove
        Dim removethese As New List(Of Control)
        ' continuous movements
        player.Top += 10
        For Each c As Control In Controls
            If c.Tag = "pipe" Or c.Tag = "score" Then
                If c.Left < -40 Then ' checking if it's off screen, then removing it if so
                    removethese.Add(c)
                Else ' if it's on screen, just move it towards the player
                    c.Left -= 10
                End If
            End If
            If c.Tag = "collider" Or c.Tag = "pipe" Then ' checking for collision
                If player.Bounds.IntersectsWith(c.Bounds) Then
                    resetgame()
                End If
            End If
            If c.Tag = "score" Then ' scoring if player goes between
                If player.Bounds.IntersectsWith(c.Bounds) Then
                    removethese.Add(c)
                    score += 1
                    scorelabel.Text = "Score: " & score
                End If
            End If
        Next
        For Each c As Control In removethese
            Controls.Remove(c)
        Next
    End Sub

现在所有的管道都同步移动,所以我对 destroy() 函数也做了同样的操作,我不再需要调用它 3 次才能正常工作。

    Public Sub destroy()
        ' list of things to remove
        Dim temp As New List(Of Control)
        ' collecting controls to remove
        For Each c As Control In Controls
            If c.Tag = "pipe" Or c.Tag = "score" Then
                temp.Add(c)
            End If
        Next
        ' removing controls
        For Each c As Control In temp
            Controls.Remove(c)
        Next
    End Sub