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 .
17 Replies - 2683 Views - Last Post: 23 April 2012 - 09:22 PM
Replies To: 2D Collision Detection in VB.NET+XNA
#3
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,
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,
#4
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.
#5
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,
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,
#6
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.
My layers are separated by using Map(X, Y, Layer#). Here is my map tile class.
Each Map(X, Y, Layer#) = a new clsMapTile. Hope this helps somewhat?
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?
#7
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
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:
'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,
Thats why I couldn't open the file
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,
#8
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.
#9
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...
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.
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,
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
#10
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.
#11
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,
Daniel,
#12
Re: 2D Collision Detection in VB.NET+XNA
Posted 21 April 2012 - 06:45 PM
Here is my new SpriteCollisionCheck function
Here is the results of it.
Up:

Down:

Left:

Right:

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.
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:

Down:

Left:

Right:

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.
#13
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
.
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)
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,
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,
#14
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?
#15
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,
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,
|
|

New Topic/Question
Reply


MultiQuote




|