Results 1 to 8 of 8

Thread: Trouble with Collision Between Objects Defined in Different Arrays

  1. #1

    Thread Starter
    New Member
    Join Date
    Jun 2016
    Posts
    5

    Unhappy Trouble with Collision Between Objects Defined in Different Arrays

    Hello.

    I've been having a major concern that I haven't been able to figure, likely because I'm just not used to debugging/looking at code critically. Perhaps I'm just being too complicated, but anyway.

    I have a single-screen top-down shooter/dungeon-kind-of game in which there's two main objects - blocks and skeletons. There are eight blocks which the player and the skeletons can't pass through, and two skeletons that the player can't touch without restarting the level.
    I've used two different arrays to define the objects that are to be skeletons or blocks, so that I don't have to name a whole bunch of objects and refer to them individually. I've been able to get the skeletons to move in the opposite direction (they currently only go right-left) when they hit a block, however the game crashes if the player restarts with an IndexOutOfRange error on the "If Skeleton(I).Bounds.IntersectsWith(Block(J).Bounds) Then" line.

    Code:
    Dim Skeleton(1) As PictureBox
    Dim Block(7) As PictureBox
    Dim obj As Object, I As Integer, J As Integer
    Dim WhichWay As Direction = Direction.Right
    Enum Direction
        Left
        Right
    End Enum
    
    Private Sub Form4_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        
    ' define which objects are "blocks" and which are "skeletons"
    
    For Each obj In Me.Controls
            If TypeOf obj Is PictureBox Then
                If obj.tag = "skeleton" Then
                    Skeleton(I) = obj
                    I += 1
                End If
                If obj.tag = "block" Then
                    Block(J) = obj
                    J += 1
                End If
            End If
        Next
    End Sub
    
    Private Sub tmrMovement_Tick(sender As Object, e As EventArgs) Handles tmrMovement.Tick
        
    ' determine skeletons' movement
    
    For I = 0 To 1
            Select Case WhichWay
                Case Direction.Left
                    Skeleton(I).Left -= 1
                Case Direction.Right
                    Skeleton(I).Left += 1
            End Select
            If Skeleton(I).Bounds.IntersectsWith(picPlayer.Bounds) AndAlso Skeleton(I).Visible = True AndAlso picPlayer.Visible = True Then
                picPlayer.Visible = False
                MsgBox("You died!" & Environment.NewLine & "Try again!")
                Reset()
            End If
    
            ' determines how the skeleton changes direction when hitting a "block" object
    
            For J = 0 To 7
                If Skeleton(I).Bounds.IntersectsWith(Block(J).Bounds) Then
                    Select Case WhichWay
                        Case Direction.Left
                            WhichWay = Direction.Right
                            Skeleton(I).Left += 1
                        Case Direction.Right
                            WhichWay = Direction.Left
                            Skeleton(I).Left -= 1
                    End Select
                End If
            Next
        Next
    End Sub
    
    Private Sub Form4_KeyDown(sender As Object, e As KeyEventArgs) Handles Me.KeyDown
        Select Case e.KeyCode
            Case Keys.Left
                tmrLeft.Start()
            Case Keys.Right
                tmrRight.Start()
            Case Keys.Down
                tmrDown.Start()
            Case Keys.Up
                tmrUp.Start()
        End Select
    
    End Sub
    
     ' the rest is just the player's movement and a function to reset the level when the player dies - so, probably not integral to the problem
    
    Private Sub Form2_KeyUp(sender As Object, e As KeyEventArgs) Handles Me.KeyUp
        Select Case e.KeyCode
            Case Keys.Left
                tmrLeft.Stop()
            Case Keys.Right
                tmrRight.Stop()
            Case Keys.Down
                tmrDown.Stop()
            Case Keys.Up
                tmrUp.Stop()
        End Select
    End Sub
    
    Private Sub tmrLeft_Tick(sender As Object, e As EventArgs) Handles tmrLeft.Tick
        picPlayer.Left -= 2
    End Sub
    
    Private Sub tmrRight_Tick(sender As Object, e As EventArgs) Handles tmrRight.Tick
        picPlayer.Left += 2
    End Sub
    
    Private Sub tmrDown_Tick(sender As Object, e As EventArgs) Handles tmrDown.Tick
        picPlayer.Top += 2
    End Sub
    
    Private Sub tmrUp_Tick(sender As Object, e As EventArgs) Handles tmrUp.Tick
        picPlayer.Top -= 2
    End Sub
    
    Private Function Reset()
        Dim frm As New Form1
        frm.Show()
        Me.Hide()
    End Function
    This code should simulate a minimalised version of the game I'm making (the actual game has shooting and a goal and other stuff)

    I can't figure anything out. I'm concerned about the fact that the game runs fine when it's first loaded, however if it's reloaded with the Reset() function, it crashes. I don't understand why the IndexOutOfRange error wouldn't occur when it's first loaded. Apparently, when the game crashes, it says that I = 2, which is good, but J = 0, which I'm pretty sure is bad. However, I don't know why it wouldn't equal 0.


    Side note - the two skeletons change direction at the same time, even if only one hits a block. Their direction is determined by the "WhichWay" variable. If I want the skeletons to not change direction in unison, do I need a different "WhichWay" integer for each skeleton to determine their direction at any given time, or is there a better way to determine the change in movement of different objects in the same array?


    Thanks in advance for any help.

  2. #2
    Lively Member
    Join Date
    Dec 2011
    Posts
    116

    Re: Trouble with Collision Between Objects Defined in Different Arrays

    I'm pretty sure I am not going to be of much assistance with your current code, however, I may be able to provide you with an alternative idea. If this is for a school project though, just move past this thought because I don't want to confuse or overly complicate your assignment.

    Currently in one application I have a dice roller app. I can have an unlimited amount of dice, but it's usually pretty buggy when I go past 10k instances on the screen. The dice is an actual class that is setup, and in that class each die handles it's own collision, with other dice that are stored in a list(of Dice), or List(of T) to google, as well as collision with the walls (or window bounds).

    For each die in that list each rendering loop I am checking to see if the index is that die, if it is then continue on to check collision with the other dice in that list.

    The point is to not have everything be in sync the skeletons would need to be an actual class, and each instance would handle it's own collision during each tick of your timer...however, an actual game loop would be much better for your purpose.

  3. #3
    Super Moderator dday9's Avatar
    Join Date
    Mar 2011
    Posts
    12,371

    Re: Trouble with Collision Between Objects Defined in Different Arrays

    You've defined your rules, the game will restart should the user or skeletons either:
    1. Touch the blocks
    2. Two specific skeletons touch the user


    What I would do to check for these two conditions is to use LINQ to get the count of blocks or skeletons that've touched the user:
    Code:
    If Blocks.Count(Function(block) block.Bounds.IntersectsWith(picPlayer.Bounds)) > 0 Then
        'Reset
    ElseIf Skeleton.Count(Function(skelly) skelly.Bounds.IntersectsWith(picPlayer.Bounds)) > 0 Then
        'Reset
    Else
        'Continue on
    End If
    Also, for what its worth this block can be condensed:
    Code:
        For Each obj In Me.Controls
            If TypeOf obj Is PictureBox Then
                If obj.tag = "skeleton" Then
                    Skeleton(I) = obj
                    I += 1
                End If
                If obj.tag = "block" Then
                    Block(J) = obj
                    J += 1
                End If
            End If
        Next
    Into these two lines:
    Code:
    Skeleton = (From pb As PictureBox In Me.Controls().OfType(Of PictureBox)() Where pb.Tag.ToString = "skeleton").ToArray()
    Blocks = (From pb As PictureBox In Me.Controls().OfType(Of PictureBox)() Where pb.Tag.ToString = "block").ToArray()
    "Code is like humor. When you have to explain it, it is bad." - Cory House
    VbLessons | HtmlLessons | CssLessons | Code Tags | Sword of Fury - Jameram

  4. #4
    Super Moderator Shaggy Hiker's Avatar
    Join Date
    Aug 2002
    Location
    Idaho
    Posts
    40,104

    Re: Trouble with Collision Between Objects Defined in Different Arrays

    Be aware that LINQ is concise, but it isn't fast. You won't see a difference in speed for something like this, since either way will appear to happen instantly, but if you find LINQ painful to read then don't worry that you're missing out.

    One thing I would suggest is that you try to make the reset work with the existing form rather than creating a new form and hiding the current. There's an issue with doing it as you are, since every object takes up a bit more memory and it never gets freed. If you hit reset enough times, the computer would crash...though it would likely take a few thousand presses before that happened, so you could ignore it. Still, truly resetting the current form is a better solution.

    In any case, you want to study this error a bit more by putting a breakpoint on the For statement in the Load event. When execution stops at the breakpoint, use F11 to step through the code. What you are specifically looking for is what gets put into each array and what the values of I and J are. I suspect that you will find that you get different results between the first time you run this and after the reload.
    My usual boring signature: Nothing

  5. #5
    Super Moderator FunkyDexter's Avatar
    Join Date
    Apr 2005
    Location
    An obscure body in the SK system. The inhabitants call it Earth
    Posts
    7,957

    Re: Trouble with Collision Between Objects Defined in Different Arrays

    The problem with your skeletons all changing direction together is because, as you have identified, they share a variable (WhichWay), and yes, the solution is to give each it's own variable.

    My suggestion would be to create a Skeleton Class with two properties: 1 A PictureBox and 2 A WhichWay variable. Your Skeletons collection would then be a collection of Skeletons, rather than a collection of PictureBoxes. (In fact, I'd probably have Skeleton, Block and Player classes because it will make each of those entities easier to manage - although the Block one might be overkill).

    I'd also second Shaggy's suggestion on the reset. Rather than create a new form it would be better to reset the state of the current one. Those dead instances are going to cause you grief.
    The best argument against democracy is a five minute conversation with the average voter - Winston Churchill

    Hadoop actually sounds more like the way they greet each other in Yorkshire - Inferrd

  6. #6

    Thread Starter
    New Member
    Join Date
    Jun 2016
    Posts
    5

    Re: Trouble with Collision Between Objects Defined in Different Arrays

    Quote Originally Posted by FunkyDexter View Post
    I'd also second Shaggy's suggestion on the reset. Rather than create a new form it would be better to reset the state of the current one. Those dead instances are going to cause you grief.
    I guess I decided to go the route I did because I didn't know how to place the skeletons back in their original positions, what with them not being individually named and all.

  7. #7
    Super Moderator FunkyDexter's Avatar
    Join Date
    Apr 2005
    Location
    An obscure body in the SK system. The inhabitants call it Earth
    Posts
    7,957

    Re: Trouble with Collision Between Objects Defined in Different Arrays

    How do you place them now? Is it just where you're positioned the picture boxes on the form?

    I don't think it matters that they're not individually named (although my Class suggestion would allow that). You don't care which skeleton starts at e.g. 50,12. You just care that a skeleton starts at 50,12. Just iterate through your Skeletons collection and set one skeleton to each starting position.
    The best argument against democracy is a five minute conversation with the average voter - Winston Churchill

    Hadoop actually sounds more like the way they greet each other in Yorkshire - Inferrd

  8. #8
    Super Moderator Shaggy Hiker's Avatar
    Join Date
    Aug 2002
    Location
    Idaho
    Posts
    40,104

    Re: Trouble with Collision Between Objects Defined in Different Arrays

    If you went with a skeleton class then you could give them starting positions as member variables. Resetting them would just be a matter of changing their current positions to those stored starting positions.

    A class is pretty much the way to go in a case like this, but it depends on where you're at. After all, you have two obvious objects: Skeletons and Blocks. Those objects have several obvsious members: Position, name, starting position, and quite possibly more. So, classes make sense.
    My usual boring signature: Nothing

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width