2D Collision Detection in VB.NET+XNA

  • (2 Pages)
  • +
  • 1
  • 2

17 Replies - 2683 Views - Last Post: 23 April 2012 - 09:22 PM

#1 bjmoreton  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 15
  • Joined: 14-July 11

2D Collision Detection in VB.NET+XNA

Posted 13 April 2012 - 07:38 AM

Hello I am having trouble detecting a collision in my 2D game I am creating. I have 5 map layers and I want to check for collision on the 2nd layer objects. I have tried numerous things and one that I am trying now is a pixelperpixel detection that I can't get to work the way it does in the tutorial I got it from located Here . The source to my project can also be found on my server .

Is This A Good Question/Topic? 0
  • +

Replies To: 2D Collision Detection in VB.NET+XNA

#2 bjmoreton  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 15
  • Joined: 14-July 11

Re: 2D Collision Detection in VB.NET+XNA

Posted 14 April 2012 - 03:38 PM

Anyone..?
Was This Post Helpful? 0
  • +
  • -

#3 DanielLeone  Icon User is offline

  • D.I.C Head

Reputation: 22
  • View blog
  • Posts: 177
  • Joined: 04-February 12

Re: 2D Collision Detection in VB.NET+XNA

Posted 19 April 2012 - 04:48 AM

Hello there bjmoreton,

You need to tell us what is exactly going wrong and weather you want help with collisions between the layers or just the collision in general; or both.

I tried downloading your project, but it can't recongnise the file type (might be something at my end?). Nice Sprite Sheet by the way :).

Provided with this information, and I might be able to help you out.

Daniel,
Was This Post Helpful? 0
  • +
  • -

#4 bjmoreton  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 15
  • Joined: 14-July 11

Re: 2D Collision Detection in VB.NET+XNA

Posted 19 April 2012 - 08:03 AM

Yes I just need help with the overall collision, between layers and collision in general. I cannot seem to figure it out, every time I get one direction working I try the same code/modified code for the other directions and it just don't work the same at all... No idea what is going on.
Was This Post Helpful? 0
  • +
  • -

#5 DanielLeone  Icon User is offline

  • D.I.C Head

Reputation: 22
  • View blog
  • Posts: 177
  • Joined: 04-February 12

Re: 2D Collision Detection in VB.NET+XNA

Posted 19 April 2012 - 07:42 PM

Hello again bjmoreton,

You've told me what you need help on, but you have to give me something to help you with, like code or something. Your project still doesn't work, so can you post your collision script here or something?

You also said collision between different layers, well it all depends on how your layers are set up, what actually differentiates them? If it was in the case of multiple lists then you could say something like if 2 objects intersect and it's contained within a certain list or something. Again I can't really help you without seeing you code.

Daniel,
Was This Post Helpful? 0
  • +
  • -

#6 bjmoreton  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 15
  • Joined: 14-July 11

Re: 2D Collision Detection in VB.NET+XNA

Posted 19 April 2012 - 07:55 PM

I don't know why the project isn't working? I mean it's in a zip file and all the project files should be there. It was made in Visual Studio 2010 VB.NET so maybe if you've got an older version maybe it don't work? I don't know haha... Anyways here is my Sprite Class.

Public Class clsSprite
    Friend Position As Vector2
    Friend Sprite As Texture2D
    Friend SpriteFrame As Integer = 1
    Friend SpriteTick As Integer = 0
    Friend MaxSpriteTicks As Integer = 10
    Friend SpriteY As Integer = 0
    Friend sRect As Rectangle
    Friend dRect As Rectangle
    Friend Speed As Integer = 1
    Friend Width As Integer = 32
    Friend Height As Integer = 32
    Friend BoundingRect As Rectangle
    Friend TextureData As Color()

    Public Enum SpriteDirs
        Up = 0
        Down = 1
        Left = 2
        Right = 3
        UpRight = 4
        UpLeft = 5
        DownRight = 6
        DownLeft = 7
        Still = 8
    End Enum

    Sub New(ByRef Texture As Texture2D)
        Sprite = Texture
        Height = CInt((Sprite.Height / 4))
        Width = CInt((Sprite.Width / 3))
        Position = New Vector2(0)
        sRect = New Rectangle(0, 0, Width, Height)
        dRect = New Rectangle(Position.X, Position.Y, 32, 32)
        BoundingRect = New Rectangle(Position.X, Position.Y, Width, Height)
        TextureData = New Color((32 * 32) - 1) {}
        'Texture.GetData(TextureData)
    End Sub

    Public Sub DrawSprite(ByRef SB As SpriteBatch)
        SB.Draw(Sprite, dRect, sRect, Color.White, 0, Vector2.Zero, SpriteEffects.None, 1)
    End Sub

    Public Sub MoveSprite(ByRef SpriteDir As SpriteDirs, ByRef tSprite As clsSprite)
        Select Case SpriteDir
            Case SpriteDirs.Up
                tSprite.SpriteY = (Height * 3)

                If Not SpriteCollisionCheck(tSprite, tSprite.Position, SpriteDir) Then
                    tSprite.Position.Y -= Speed
                End If
            Case SpriteDirs.Down
                tSprite.SpriteY = 0

                If Not SpriteCollisionCheck(tSprite, tSprite.Position, SpriteDir) Then
                    tSprite.Position.Y += Speed
                End If
            Case SpriteDirs.Left
                tSprite.SpriteY = (Height * 1)

                tSprite.Position.X -= Speed
            Case SpriteDirs.Right
                tSprite.SpriteY = (Height * 2)

                tSprite.Position.X += Speed
            Case SpriteDirs.UpLeft
                tSprite.Position.Y -= 1
                tSprite.Position.X -= 1
            Case SpriteDirs.UpRight
                tSprite.Position.Y -= 1
                tSprite.Position.X += 1
            Case SpriteDirs.DownLeft
                tSprite.Position.Y += 1
                tSprite.Position.X -= 1
            Case SpriteDirs.DownRight
                tSprite.Position.Y += 1
                tSprite.Position.X += 1
            Case SpriteDirs.Still
                tSprite.SpriteFrame = 1
        End Select

        If tSprite.SpriteFrame = 0 And Not SpriteDir = SpriteDirs.Still And tSprite.SpriteTick >= tSprite.MaxSpriteTicks Then
            tSprite.SpriteFrame = 1
            tSprite.SpriteTick = 0
        ElseIf tSprite.SpriteFrame = 1 And Not SpriteDir = SpriteDirs.Still And tSprite.SpriteTick >= tSprite.MaxSpriteTicks Then
            tSprite.SpriteFrame = 2
            tSprite.SpriteTick = 0
        ElseIf tSprite.SpriteFrame = 2 And Not SpriteDir = SpriteDirs.Still And tSprite.SpriteTick >= tSprite.MaxSpriteTicks Then
            tSprite.SpriteFrame = 0
            tSprite.SpriteTick = 0
        End If

        tSprite.SpriteTick += 1

        sRect = New Rectangle((tSprite.SpriteFrame * Width), SpriteY, tSprite.Width, tSprite.Height)
        dRect = New Rectangle(tSprite.Position.X, tSprite.Position.Y, 32, 32)
    End Sub

    Public Function SpriteCollisionCheck(ByRef tSprite As clsSprite, ByRef SpritePos As Vector2, ByRef SpriteDir As SpriteDirs) As Boolean
        Dim ToonX As Double = (SpritePos.X / 32), ToonY As Double = (SpritePos.Y / 32)
        Dim Distance As Double = 0
        tSprite.BoundingRect = New Rectangle(ToonX, ToonY, tSprite.Width, tSprite.Height)
        Select Case SpriteDir
            Case SpriteDirs.Up
                If Not IsNothing(Map(ToonX, ToonY, 2)) Then
                    If Not Map(ToonX, ToonY, 2).Passable Then
                        Distance = ((SpritePos - Map(ToonX, ToonY, 2).TilePos).Length / 32)
                        Debug.Print(Distance)
                        If Distance > ToonY Then
                            Return True
                        End If
                    End If
                End If
' DOWN doesn't work only UP does...
            Case SpriteDirs.Down
                If Not IsNothing(Map(ToonX, (ToonY + 1), 2)) Then
                    If Not Map(ToonX, (ToonY + 1), 2).Passable Then
                        Distance = ((SpritePos - Map(ToonX, (ToonY + 1), 2).TilePos).Length / 32)
                        Debug.Print("Down:" & Distance)
                    End If
                End If
            Case SpriteDirs.Left
                    Return False
            Case SpriteDirs.Right
                    Return False
            Case SpriteDirs.UpLeft
                    Return False
            Case SpriteDirs.UpRight
                    Return False
            Case SpriteDirs.DownLeft
                    Return False
            Case SpriteDirs.DownRight
                    Return False
            Case Else
                    Return False
        End Select
    End Function
End Class



My layers are separated by using Map(X, Y, Layer#). Here is my map tile class.

Public Class clsMapTile
    ' Tile Properties
    Public Texture As Texture2D
    Public FullString As String = Nothing
    Public Passable As Boolean = True
    Public Pos As Vector3 = Vector3.Zero
    Public TilePos As Vector2 = Vector2.Zero
    Public Width As Integer = 0
    Public Height As Integer = 0
    Public BoundingRect As Rectangle
    Public TextureData As Color()

    Public Sub New(ByRef X As Integer, ByRef Y As Integer, ByRef Z As Integer, ByRef tPassable As Boolean, ByRef tFullString As String, ByRef tTilePos As Vector2, ByRef tTexture As Texture2D)
        Passable = tPassable
        FullString = tFullString
        Pos = New Vector3(X, Y, Z)
        TilePos = tTilePos
        BoundingRect = New Rectangle(X, Y, 32, 32)
        TextureData = New Color((32 * 32) - 1) {}
        'Texture = tTexture
        'Texture.GetData(TextureData)
    End Sub
End Class



Each Map(X, Y, Layer#) = a new clsMapTile. Hope this helps somewhat?
Was This Post Helpful? 0
  • +
  • -

#7 DanielLeone  Icon User is offline

  • D.I.C Head

Reputation: 22
  • View blog
  • Posts: 177
  • Joined: 04-February 12

Re: 2D Collision Detection in VB.NET+XNA

Posted 19 April 2012 - 11:45 PM

I'm not familiar at all with the VB syntax, so I don't really understand what a lot of your code does.
Thats why I couldn't open the file :D thought it was C# hahaha.

If you have an integer in you clsMapTile, then could you put an integer in your Collision function so when you call it, it goes something like this:

 If Not SpriteCollisionCheck(tSprite, tSprite.Position, SpriteDir, 1) Then...


'1' being the layer you want.

Hope that makes sense.
As for your collisions, I can't really suggest anything because as I said I am very unfamiliar with VB so I am sorry for the misunderstanding.

Hope I helped anyway,
Daniel,
Was This Post Helpful? 0
  • +
  • -

#8 bjmoreton  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 15
  • Joined: 14-July 11

Re: 2D Collision Detection in VB.NET+XNA

Posted 20 April 2012 - 08:13 PM

Well how would suggest doing collisions in C#? I could easily change the code from C# to VB.NET. I have still not found a way of doing collisions have been trying for over 2 weeks now. :(
Was This Post Helpful? 0
  • +
  • -

#9 DanielLeone  Icon User is offline

  • D.I.C Head

Reputation: 22
  • View blog
  • Posts: 177
  • Joined: 04-February 12

Re: 2D Collision Detection in VB.NET+XNA

Posted 20 April 2012 - 11:39 PM

If you plan on using bounding box and not per pixel collision, then there is a method in the Rectangle class called Intersect().

So I don't now how it would work in VB, but you could say something like...

foreach(Sprite s in spriteList)
{
    if (s.area.Intersects(area)
    {
        return true;
    }
}
return false;



So that basically says if any sprite from a List intersects with the current sprite, then it returns true.

So if could change you SpriteCollisionCheck function to return a boolean, then take a Sprite and integer as parametres, then you could do something like this, but obviously in VB.

public bool SpriteCollisionCheck(Sprite s, int layer)
{
    foreach(Sprite sprite in spriteList)
    {
       if(s.area.Intersects(sprite.area) && s.layer == layer)
       {
          return true;
       }
    }
}



This code loops though all the sprites in a list, and if there area (bounding area in rectagle), intersects with the parametres area, and it is on the same layer as the parameter integer, then it returns true;

As I said, I don't know really anything about VB syntax, but I hope that helped.

If the rectangle class doesn't have a Intersect method, try right clicking on the work 'Rectangle' and then 'Go To Definition', take a look through some of the stuff in there, that might be of use, but I wouldn't see why it wouldn't have it.

I hope that sort of helped ;),
Let me know I can be of any more assistance,
Daniel,

This post has been edited by DanielLeone: 20 April 2012 - 11:41 PM

Was This Post Helpful? 0
  • +
  • -

#10 bjmoreton  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 15
  • Joined: 14-July 11

Re: 2D Collision Detection in VB.NET+XNA

Posted 21 April 2012 - 07:12 AM

last time i tried to use the intersect method of the rectangle my sprite moves half-way intthe bounding area rectangle then stops. I can post a picture showing what i am talking about when i get home later today.
Was This Post Helpful? 0
  • +
  • -

#11 DanielLeone  Icon User is offline

  • D.I.C Head

Reputation: 22
  • View blog
  • Posts: 177
  • Joined: 04-February 12

Re: 2D Collision Detection in VB.NET+XNA

Posted 21 April 2012 - 06:13 PM

Yeah a common problem in C#, is people forget to 'update' the area, so it actually never follows the player/spite, and stays where it was first initialized. That may be the problem, but I will see if you post a picture.

Daniel,
Was This Post Helpful? 0
  • +
  • -

#12 bjmoreton  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 15
  • Joined: 14-July 11

Re: 2D Collision Detection in VB.NET+XNA

Posted 21 April 2012 - 06:45 PM

Here is my new SpriteCollisionCheck function

    Public Function SpriteCollisionCheck(ByRef tSprite As clsSprite, ByRef SpritePos As Vector2, ByRef SpriteDir As SpriteDirs, ByRef Layer As Integer) As Boolean
        Dim ToonX As Double = (SpritePos.X / 32), ToonY As Double = (SpritePos.Y / 32)
        Dim Distance As Double = 0

        'tSprite.Width = 32
        'tSprite.Height = 32
        'X&Y is based on Sprites position
        tSprite.BoundingRect = New Rectangle(ToonX, ToonY, tSprite.Width, tSprite.Height)

        If Not IsNothing(Map(ToonX, ToonY, Layer)) Then
            If Not Map(ToonX, ToonY, 2).Passable Then
                'Map Rectangle width and height is also 32x32
                'X&Y is the tile under the sprite.
                If tSprite.BoundingRect.Intersects(Map(ToonX, ToonY, Layer).BoundingRect) Then
                    Return True
                Else
                    Return False
                End If
            Else
                Return False
            End If
        Else
            Return False
        End If
    End Function



Here is the results of it.
Up:
Posted Image

Down:
Posted Image

Left:
Posted Image

Right:
Posted Image


All directions you get 'stuck' meaning if you go left, then when you try to walk away to the right,up or down the sprite goes nowhere. Same happens if you go up you cannot go back down,left or right. If you need me to actually show the rectangles of the tiles/sprite I can.
Was This Post Helpful? 0
  • +
  • -

#13 DanielLeone  Icon User is offline

  • D.I.C Head

Reputation: 22
  • View blog
  • Posts: 177
  • Joined: 04-February 12

Re: 2D Collision Detection in VB.NET+XNA

Posted 22 April 2012 - 02:08 AM

Okay the sprites getting stuck is a simple explanation, and if it all works except for that then you're in a good position :D.

Basically your code will return true if the sprite is touching a wall, and will only move if it isn't touching a wall. That means that as soon as you touch a wall, it will return true, and not let you move. If you then try to move in the opposite direction it will still return true, because you haven't actually moved yet. Make sense?

To fix this you need to get another rectangle equal to an offset of your current BoundingRect.

Again I don't know how to do this in VB but in C# you can do it like this. (It's very simple anyway)

            Rectangle newArea = new Rectangle(area.X, area.Y, area.Width, area.Height);
            newArea.X += offSetX;
            newArea.Y += offSetY;



The two offset variables are in the constructor, and instead of using tSprite.BoundingRectangle, you would use newArea.

Basically newArea is a replica of tSprite.BoundingRect in you situation, plus the offset.
Then you test the collision with newArea.

So with adding the offset integers to your constructor, calling it should have the speed value of whatever you use as movement.

Hope that made sense,
Daniel,
Was This Post Helpful? 0
  • +
  • -

#14 bjmoreton  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 15
  • Joined: 14-July 11

Re: 2D Collision Detection in VB.NET+XNA

Posted 22 April 2012 - 04:30 PM

Well now the sprite doesn't get stuck. But if you look at the pictures I posted the sprite still walks about half-way into the rocks when walking downwards and somewhat into the build while walking left or right. How can I fix this problem?
Was This Post Helpful? 0
  • +
  • -

#15 DanielLeone  Icon User is offline

  • D.I.C Head

Reputation: 22
  • View blog
  • Posts: 177
  • Joined: 04-February 12

Re: 2D Collision Detection in VB.NET+XNA

Posted 23 April 2012 - 01:05 AM

Maybe check the bounding rectangles of both your sprite, and rocks/objects.

I noticed that you also use 32 as both the tSprite.Width and tSprite.Height, I believe this is probably your problem.

I would recommend getting these values of the tSprite.Texture.Width is such a thing exists and not just numbers of the top of your head, if you know what I mean, because what if you changed your sprite, then you would have to sort through all your code and change multiple values that could easily be mistaken. Hope you see what I am getting at.

If you don't have, or can't access the texture.Width and Height, or simply don't want to do it that way, you can test to see if these values are the problem, but drastically increasing them, too something like 100, and see what happens.

Hope I've helped,
Daniel,
Was This Post Helpful? 0
  • +
  • -

  • (2 Pages)
  • +
  • 1
  • 2