Background: I'm trying to make a Flappy Bird-esque game in Visual Basic to familiarise myself with the language (I'm going to need to code with it for the next 2 years, I don't really get a choice).
The issue is with continuous movement of the pipes. The pipes are generated every 1200ms. The game checks for each control tagged "pipe"
and "score"
and moves it based on another timer with interval 60ms. Code for gameloop
timer:
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
The bottom pipe and the scoring zone both move in sync with one another, but the top one seemingly lags behind a little bit (all 3 should move together), and gets progressively worse as the game goes, see here. Scoring zone is made pink for clarity.
I'm not sure what's causing this issue. I checked the elapsed time for both the gameloop
and pipegen
timer, the code for both of which executes well within the timer interval. I also tried replacing the logic with a case statement but it still didn't change the desynchronisation. I personally couldn't find anything related to this online. Is it an issue with pictureboxes, VB or have I made a silly mistake (which is entirely possible, I'm very new to the language).
Here's the full code on pastebin.
Thanks!
The major error I made in the code was removing from an array while looping through it. Instead I made a list of controls to delete and looped through that afterwards:
' 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
All the pipes now move in sync so I did the same for the destroy()
function, I no longer need to call it 3 times for it to work.
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