Question Collision Detection

xstone4

Member
Joined
Jul 11, 2011
Messages
6
Programming Experience
3-5
Hey guys just a quick question that i am sure someone can answer easy for me.

The past 3 days iv been working on getting collision detection working on the edge of a form as you will see from my code in a min i have a command button on a form that you can move with the arrow keys. Iv had sucsess with the top collision detection that one works and i got that working within an hour of trying to write the collision detection. How ever the bottem the left and the right seem un mathimatical to me as iv tryed adding and subtracting almost every combonation (Bottem,top,height,location,size) it is on a sizeable form so the collision detection must be flexable not set.

I have looked for ansers all over the internet and found a lot of good examples of set rectangle collision detection. Which i have tryed to modify to be flexable for what i want but it caused errors and one of them worked backwards... the button went off the screen but would not come back.

I have a good knolage of VB6 from when i was back in college and i remember one of my friends there made a collision detection statment that i used and tweeked for a few things but as iv found VB6 code won't fly with VB.Net.

Anyway here is my code have a look and please sugest something which is so simple i can slap myself in the face for not seeing it.

Private Sub BlackAndWhite_KeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles Me.KeyDown
        
        Dim up As Boolean = False
        Dim left As Boolean = False
        Dim down As Boolean = False
        Dim right As Boolean = False


        If GetAsyncKeyState(Keys.Up) Then up = True
        If GetAsyncKeyState(Keys.Left) Then left = True
        If GetAsyncKeyState(Keys.Down) Then down = True
        If GetAsyncKeyState(Keys.Right) Then right = True


        If Me.Location.Y - Me.Location.Y = Button1.Location.Y Then
            up = False
        End If
        If up = True And right = True Then
            Button1.Left = Button1.Left + 10
            Button1.Top = Button1.Top - 10
        ElseIf up = True And left = True Then
            Button1.Left = Button1.Left - 10
            Button1.Top = Button1.Top - 10
        ElseIf down = True And right = True Then
            Button1.Left = Button1.Left + 10
            Button1.Top = Button1.Top + 10
        ElseIf down = True And left = True Then
            Button1.Left = Button1.Left - 10
            Button1.Top = Button1.Top + 10
        ElseIf right = True And up = False And down = False Then
            Button1.Left = Button1.Left + 10
        ElseIf left = True And up = False And down = False Then
            Button1.Left = Button1.Left - 10
        ElseIf up = True And right = False And left = False Then
            Button1.Top = Button1.Top - 10
        ElseIf down = True And right = False And left = False Then
            Button1.Top = Button1.Top + 10
        End If

    End Sub
 
You would use the Top, Left, Bottom and Right properties of the Button. You would compare the Top and Left to zero, which is easy. The Bottom and Right would be compared to the Height and Width properties of the form's ClientSize property, not of the form itself. Also, don't set the vertical and horizontal components separately.
Private Const INCREMENT As Integer = 10

Private Function ShiftUp(bounds As Rectangle) As Rectangle
    bounds.Offset(0, -Math.Min(INCREMENT, bounds.Top))

    Return bounds
End Function

Private Function ShiftLeft(bounds As Rectangle) As Rectangle
    bounds.Offset(-Math.Min(INCREMENT, bounds.Left), 0)

    Return bounds
End Function

Private Function ShiftDown(bounds As Rectangle) As Rectangle
    bounds.Offset(0, Math.Min(INCREMENT, Me.ClientSize.Height - bounds.Bottom))

    Return bounds
End Function

Private Function ShiftRight(bounds As Rectangle) As Rectangle
    bounds.Offset(Math.Min(INCREMENT, Me.ClientSize.Width - bounds.Right), 0)

    Return bounds
End Function
Now all you have to do is call the appropriate one or two of those methods to move the control and it will never go beyond the bounds of the form, e.g.
Me.Button1.Bounds = ShiftDown(ShiftRight(Me.Button1.Bounds))
That will move the Button down and right but never beyond the right and lower edges of the form.

If you want to move the button to keep it inside the form when the form shrinks, that's another matter.
 
fixed

In truth i got a syntax error when calling the functions but you pointed me in the right direction and iv managed to work something out.

        If Button1.Top = 0 And Button1.Left = 0 Then
            up = False
            left = False
        ElseIf Button1.Bottom > Me.ClientSize.Height And Button1.Left = 0 Then
            left = False
            down = False
        ElseIf Button1.Top = 0 And Button1.Right > Me.ClientSize.Width Then
            up = False
            right = False
        ElseIf Button1.Bottom > Me.ClientSize.Height And Button1.Right > Me.ClientSize.Width Then
            right = False
            down = False
        ElseIf Button1.Top = 0 Then
            up = False
        ElseIf Button1.Left = 0 Then
            left = False
        ElseIf Button1.Right > Me.ClientSize.Width Then
            right = False
        ElseIf Button1.Bottom > Me.ClientSize.Height Then
            down = False
        End If
 
The code worked for me in VB 2010 so either it's something to do with an older version (although I can't see anything that would be an issue) or else you've done something wrong. If you don;t tell me what you did, i.e. your exact code, and what happened, i.e. the error message(s), then I can't help.
 
Im useing 2008 Express Edition. I Basicly did this when trying your method

ElseIf up = True And right = False And left = False Then
           ' Button1.Top = Button1.Top - 10
Call ShiftUp()
 
I don't think that you looked at my example very hard. This what I posted:
Me.Button1.Bounds = ShiftDown(ShiftRight(Me.Button1.Bounds))
Each of those four methods expects you to pass it a Rectangle and it returns a Rectangle to you that is the original but shifted in the appropriate direction. You are supposed to get the original Bounds of the control, pass that in to the method and it passes you back the new value, which you then assign to the control's Bounds property, just as I did in my example. My example shows two methods being called: ShiftDown and ShiftRight. It should be obvious from that that the control will move diagonally, down and right. If you only want to shift in one direction then you only call one method.

So, that's what you did wrong, but we would never have known if you kept it all a secret. Whenever something doesn't work, tell us exactly what you id and tell us exactly what happened. Code and error messages are the first things you look for in that regard.
 
You can also just offset the new rectangle and check if that would fit before assigning it:
Dim rct = Me.Button1.Bounds

If CBool(GetAsyncKeyState(Keys.Down)) Then rct.Offset(0, 10)
If CBool(GetAsyncKeyState(Keys.Up)) Then rct.Offset(0, -10)
If CBool(GetAsyncKeyState(Keys.Left)) Then rct.Offset(-10, 0)
If CBool(GetAsyncKeyState(Keys.Right)) Then rct.Offset(10, 0)

If Me.ClientRectangle.Contains(rct) Then Me.Button1.Bounds = rct

Rectangle.Contains method used here does all the border calculations for you.
 
I like both of these idears more than i like the way i have done it. But at the same time i have realized some problems with the Clientsize it's not the same value as the form size as the form size is default 300x300 but the clientsize is not 300x300 as the button starts at location.y 20 location.x 130.

On the left and top the collision detection is perfect no matter what size the form but on the right and bottom i had to set it to > instead of = otherwise it wouldent work and even with form at default size (300x300) it overlaps on right and bottom as these pictures show.

zojl88.jpg

53l4hv.jpg

Will useing one of these other methods avoid this or is this un avoidable with a sizeable form?

Thats better (Edited Post)

Thinking of writeing a step back overlap error catcher something like this (this is just quicky writen code so i know it probly won't work)

Dim cruncher As Integer
If Button1.Bottom > Me.Clientsize.Height Then
cruncher = Button1.Bottom - Me.Clientsize.Height
Button1.Bottom = Button1.Bottom - cruncher
End If


Basicly what im getting at is if the button bottom is at 304 on the form which is 300x300 then it - 300 from 304 and moves the button up by 4 createing the perfect collision (in theory)
I know its going to be more complex then that but im taking a little break as after fixing the collisions last night i went on to write a bit more for my media player.
 
Last edited:
Finaly Working how i want

Finaly got the collision detection working how i want it to and by removing the overlap after the movment has be stoped because of the collision its given the button a nice bounce off effect when you hit a wall once. I have managed to avoid the jerking that some collision detection gives by stoping movment when a colission is detected instead of pushing the button back when a collision is detected.

Here is my final code feel free to say ways i could improve it or how i could make it simpler. Thank you JohnH and Jmcilhinney For your idears and help.

Private Sub BlackAndWhite_KeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles Me.KeyDown

        Dim up As Boolean = False
        Dim left As Boolean = False
        Dim down As Boolean = False
        Dim right As Boolean = False
        Dim correction As Integer

        If GetAsyncKeyState(Keys.Up) Then up = True
        If GetAsyncKeyState(Keys.Left) Then left = True
        If GetAsyncKeyState(Keys.Down) Then down = True
        If GetAsyncKeyState(Keys.Right) Then right = True

        If Button1.Top <= 0 And Button1.Left <= 0 Then
            correction = Button1.Top
            Button1.Top = Button1.Top - correction
            correction = Nothing
            correction = Button1.Left
            Button1.Left = Button1.Left - correction
            up = False
            left = False
        ElseIf Button1.Bottom >= Me.ClientSize.Height And Button1.Left <= 0 Then
            correction = Button1.Bottom - Me.ClientSize.Height
            Button1.Top = Button1.Top - correction
            correction = Nothing
            correction = Button1.Left
            Button1.Left = Button1.Left - correction
            left = False
            down = False
        ElseIf Button1.Top <= 0 And Button1.Right >= Me.ClientSize.Width Then
            correction = Button1.Top
            Button1.Top = Button1.Top - correction
            correction = Nothing
            correction = Button1.Right - Me.ClientSize.Width
            Button1.Left = Button1.Left - correction
            up = False
            right = False
        ElseIf Button1.Bottom >= Me.ClientSize.Height And Button1.Right >= Me.ClientSize.Width Then
            correction = Button1.Bottom - Me.ClientSize.Height
            Button1.Top = Button1.Top - correction
            correction = Nothing
            correction = Button1.Right - Me.ClientSize.Width
            Button1.Left = Button1.Left - correction
            right = False
            down = False
        ElseIf Button1.Top <= 0 Then
            correction = Button1.Top
            Button1.Top = Button1.Top - correction
            up = False
        ElseIf Button1.Left <= 0 Then
            correction = Button1.Left
            Button1.Left = Button1.Left - correction
            left = False
        ElseIf Button1.Right >= Me.ClientSize.Width Then
            correction = Button1.Right - Me.ClientSize.Width
            Button1.Left = Button1.Left - correction
            right = False
        ElseIf Button1.Bottom >= Me.ClientSize.Height Then
            correction = Button1.Bottom - Me.ClientSize.Height
            Button1.Top = Button1.Top - correction
            down = False
        End If

        If up = True And right = True Then
            Button1.Left = Button1.Left + 10
            Button1.Top = Button1.Top - 10
        ElseIf up = True And left = True Then
            Button1.Left = Button1.Left - 10
            Button1.Top = Button1.Top - 10
        ElseIf down = True And right = True Then
            Button1.Left = Button1.Left + 10
            Button1.Top = Button1.Top + 10
        ElseIf down = True And left = True Then
            Button1.Left = Button1.Left - 10
            Button1.Top = Button1.Top + 10
        ElseIf right = True And up = False And down = False Then
            Button1.Left = Button1.Left + 10
        ElseIf left = True And up = False And down = False Then
            Button1.Left = Button1.Left - 10
        ElseIf up = True And right = False And left = False Then
            Button1.Top = Button1.Top - 10
        ElseIf down = True And right = False And left = False Then
            Button1.Top = Button1.Top + 10
        End If

    End Sub
 
Back
Top