图片框移动不同步
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. 为了清晰起见,得分区被设为粉红色。
我不确定是什么导致了这个问题。我检查了 gameloop
和 pipegen
计时器的运行时间,两者的代码在计时器间隔内执行良好。我也尝试用 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
背景:我正在尝试用 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. 为了清晰起见,得分区被设为粉红色。
我不确定是什么导致了这个问题。我检查了 gameloop
和 pipegen
计时器的运行时间,两者的代码在计时器间隔内执行良好。我也尝试用 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