0

I am creating a video game using Visual Basic .NET for IPT at school.

The game is a top-down shooter/adventure in which the player controls their character going up, down, left, right, and diagonally, and must acquire an object to finish the level. On the way are enemies and obstacles that block or kill the player character.

I'm trying to figure out a simple way to assign all the picture boxes meant to be obstacles as...well, obstacles that block the player, and then have the player's movement timer in whichever direction stop by changing into a long interval (if I just make the timer stop, it will start again as the arrow key is being held, thus resulting in stuttering in place as the player holds the arrow key in that direction). For the sake of this question, I only included an if statement for the player's "up" movement.

I have been using some code I found out with our textbook to identify "enemies", in which I create an array and define an object as obj and integer as I, then for each control in the form, check if it is a picture box and has a specific tag, then if it does, assign it to the array. Then for stuff like collision, for I = 0 To whatever, if the player intersects with the assigned objects, stuff happens yadda yadda. Like this:

Public Class Form2
Dim Skeleton(1) As PictureBox

Private Sub Form2_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        Dim obj As Object, I As Integer = 0
For Each obj In Me.Controls
            ' assign picture boxes with "skeleton" tag to Skeleton array
            If TypeOf obj Is PictureBox AndAlso obj.tag = "skeleton" Then
                Skeleton(I) = obj
                I += 1
            End If
        Next

Private Sub tmrMovement_Tick(sender As Object, e As EventArgs) Handles tmrMovement.Tick
        For I = 0 To 1
            If Collision(Skeleton(I), picPlayer) Then
                picPlayer.Visible = False
                MsgBox("You died!" & Environment.NewLine & "Try again!")
                Reset()
            End If

It worked fine. So I figured if I want to quickly identify blocks that are meant to be impassable by the player, I'd just use another integer J and object otherobj, and another array. For example:

Public Class Form2
    Dim Border(7) As PictureBox

Private Sub Form2_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        Dim obj As Object, I As Integer = 0, otherobj As Object, J As Integer = 0
        For Each otherobj In Me.Controls
            ' Assign picture boxes with "border" tag to Border array
            If TypeOf otherobj Is PictureBox AndAlso otherobj.tag = "border" Then
                Border(J) = otherobj
                J += 1
            End If
        Next

Private Sub PicPlayer_LocationChanged(sender As Object, e As EventArgs) Handles picPlayer.LocationChanged
For J = 0 To 7
            If Border(J).Bounds.IntersectsWith(picPlayer.Bounds) Then
                If tmrUp.Enabled Then
                    tmrUp.Stop()
                    tmrUp.Interval = 10000
                End If
            End If
        Next

However, I'm getting a null reference exception, and on run-time the assigning never happens and J remains 0. However, I have a private sub for a timer ticking (a timer which is always enabled, for I have used it for enemy movement), and if the for each loop is in that sub, instead of the picPlayer_LocationChanged sub, then it does work! The objects have collision!

My (new) Question: Why is it that the iteration shows a NullReferenceException error in a LocationChanged event for the player object, but it works perfectly fine if I have it in a Tick event for a timer?

K-leb
  • 9
  • 4

1 Answers1

0

Your problem is that you trying to do something when controls are not there yet. Form load event starts when form is starting loading. Solution to this would be using form shown event which happens after form loads:

Private Sub Form1_Shown(sender as Object, e as EventArgs) Handles Form1.Shown
   MessageBox.Show("You are in the Form.Shown event.")
End Sub

Also you can loop through just picture boxes. Applying this solution you can something like this:

Dim i As Integer = 0
For Each pictureBox As var In PictureTab.Controls.OfType(Of PictureBox)()
    pictureBox.Picture = cboProperty.Column(i)
    i += 1
Next
Community
  • 1
  • 1
Claudius
  • 1,813
  • 1
  • 15
  • 31