Sign in to follow this  
Diirewolf

Simple collision detection for sidescroller

Recommended Posts

Diirewolf    122
Ive been working for awhile on a sidescroller and I was wondering what is the best way to do collision detection. I'm using C# with Managed DirectX, my game is pretty simple. I have a Sprite class, Tiles are just Rectangles and are organized into a List<Tile> variable for a level. I have a static class Collision which has some collision functions. Currently I just have a function SpriteSpriteCollision(Sprite s1, sprite s2) which returns a Direction (ie. the direction that s1 is in terms of s2). My code checks if the SpriteOldRectangle of s1 is on the left, top, right or bottom of s2 and returns a Direction based on that. Of couse I check if the 2 sprites are colliding first. Now I'm not sure if my way of doing the collision detection is right, in fact im sure there is a better way to do it. Also with my way the collision response doesn't work well most of the time. Can someone explain to me the best way to do collision detection (and respose) in a sidescroller game. note i dont want pixel accurate collision detection (at least not yet :) ). Thanks

Share this post


Link to post
Share on other sites
jyk    2094
SAT (separating axis theorem) with MTD (minimum translation distance/vector) would probably work well for this (it would give natural 'sliding' collision response, among other things).

It sounds a little complicated, but for AABBs it's actually quite simple and reduces to just a few lines of code.

You could google using the above terms, but it'd probably be just as easy to figure it out yourself. Draw two overlapping AABBs in any configuration, and then ask the question, what is the shortest distance and (axis-aligned) direction I can move one of the boxes so that the intersection is resolved? This is essentially the question you have to answer (in code, of course) to implement the algorithm.

Share this post


Link to post
Share on other sites
Sirisian    2263
Like this?

www.sirisian.templarian.com/flash/flashplatform.swf
(click on it and arrow keys)

I wrote it in flash in about 5 minutes for a friend... here's the source, it's C-Syntax shouldn't take long to convert it.

For some reason I used two iterations for the hitdetection. You can easily turn it into one iteration. Here are the simple variables.
this.velocityX is object's velocity for X
this.velocityY is object's velocity for Y
this.vx is the x coord for object
this.vy is the y coord for object
object in this case was a unit. use a nested for loop for iteration through two arrays of objects.
This does what JYK is saying all you have to do is optimize it.

this.vx += this.velocityX;
for (var wallItr = 0; wallItr<wallArray.length; ++wallItr) {
if (this.vx<wallArray[wallItr].vx+wallArray[wallItr].vwidth) {
if (this.vx+this.vwidth>wallArray[wallItr].vx) {
if (this.vy<wallArray[wallItr].vy+wallArray[wallItr].vheight) {
if (this.vy+this.vheight>wallArray[wallItr].vy) {
if (this.velocityX<0) {
this.vx = wallArray[wallItr].vx+wallArray[wallItr].vwidth;
this.velocityX = 0;
} else if (this.velocityX>0) {
this.vx = wallArray[wallItr].vx-this.vwidth;
this.velocityX = 0;
}
}
}
}
}
}
this.vy += this.velocityY;
for (var wallItr = 0; wallItr<wallArray.length; ++wallItr) {
if (this.vx<wallArray[wallItr].vx+wallArray[wallItr].vwidth) {
if (this.vx+this.vwidth>wallArray[wallItr].vx) {
if (this.vy<wallArray[wallItr].vy+wallArray[wallItr].vheight) {
if (this.vy+this.vheight>wallArray[wallItr].vy) {
if (this.velocityY<0) {
this.vy = wallArray[wallItr].vy+wallArray[wallItr].vheight;
this.velocityY = 0;
} else if (this.velocityY>0) {
this.vy = wallArray[wallItr].vy-this.vheight;
this.velocityY = 0;
this.HitGround();
}
}
}
}
}
}



Share this post


Link to post
Share on other sites
Diirewolf    122
I understand Sirisian's method and I just wrote up a quick GDI test and it works like a charm. I have read on SAT and I dont know if it would be smart to use it in a sidescroller. You think its worth learning and implementing it into a sidescroller?
thanks

Share this post


Link to post
Share on other sites
oliii    2196
it's not very hard, but it depends what you need. For square tiles, it would be very easy. It's basically like doing a ray vs a box intersection test.

Share this post


Link to post
Share on other sites
jyk    2094
Quote:
Original post by Diirewolf
I have read on SAT and I dont know if it would be smart to use it in a sidescroller.
Why not? The SAT is perfectly suited for collision detection between convex polygonal objects in 2D (which includes AABBs).

Anyway, the code of Sirisian's that you're using is an SAT test, so the question of whether the SAT is appropriate for this context is pretty much moot :)

Share this post


Link to post
Share on other sites
jyk    2094
Quote:
Original post by Diirewolf
What is the advantage of using SAT method vs Normal method (the one that Sirisian used)?
As noted above, Sirisian is using the SAT.

Share this post


Link to post
Share on other sites
Sirisian    2263
oh thank god it worked... I just tore it out and figured it did something right. I learned SAT like 5 months ago. The MTD still confuses me to no end with convex polygons. Except with AABB it's rather obvious.

Optimize my code though, I'm just glad it worked.

here's an unoptimized SAT for two AABB boxes given x,y,w,h

if(object1.x < object2.x+object2.w && object1.x+object1.w > object2.x && object1.y < object2.y+object2.h && object1.y+object1.h > object2.y){
//They are hitting
}


that code is good for doing preliminary quick checks with high vertex convex polygons.

Share this post


Link to post
Share on other sites
Diirewolf    122
The way i'm doing it now is simple SAT only rectangles:

public enum Direction { None, Left, Top, Right, Bottom }

public static class Collision{

public static bool RectsAreColliding(Rectangle r1, Rectangle, r2)
{
return (!((r1.Right < r2.Left) || (r1.Left > r2.Right) || (r1.Bottom < r2.Top) || (r1.Top > r2.Bottom)));
}

public static Direction SpriteRectXCollision(Sprite sprite, Rectangle rect/*probably a tile*/)
{
if (!RectsAreColliding(sprite.SpriteRectangle, rect))
{
return Direction.None;
}

if (sprite.VelocityX > 0)
{
return Direction.Right;
}
else if (sprite.VelocityX < 0)
{
return Direction.Left;
}

return Direction.None;
}

public static Direction SpriteRectYCollision(Sprite sprite, Rectangle rect/*probably a tile*/)
{
if (!RectsAreColliding(sprite.SpriteRectangle, rect))
{
return Direction.None;
}

if (sprite.VelocityY > 0)
{
return Direction.Bottom;
}
else if (sprite.VelocityY < 0)
{
return Direction.Top;
}

return Direction.None;
}

}

Pretty optimized I think and it works perfectly.

Share this post


Link to post
Share on other sites
Azaykon    122
I have a question with the SAT test.
How will you find the intersection time with a moving box against a line segment using the SAT test (2 dimensional objects). I know how to find it if there where two boxes but the line segment is causing me problems because its normal could be pointing in any direction. Checking with boxes you check only the x and y axes. My box has a center point c and two radiuses in a 2 dimensional array ([0] -> width, [1] -> height). My line segment consists (obviously) of two points. I am using the lines parallell to the edge normals as separating axes. I have no problems finding the normals but I don't now how to do this check. Could someone please help me?

Share this post


Link to post
Share on other sites
jyk    2094
Quote:
Original post by Azaykon
I have a question with the SAT test.
How will you find the intersection time with a moving box against a line segment using the SAT test (2 dimensional objects). I know how to find it if there where two boxes but the line segment is causing me problems because its normal could be pointing in any direction. Checking with boxes you check only the x and y axes. My box has a center point c and two radiuses in a 2 dimensional array ([0] -> width, [1] -> height). My line segment consists (obviously) of two points. I am using the lines parallell to the edge normals as separating axes. I have no problems finding the normals but I don't now how to do this check. Could someone please help me?
For the line segment there is only one axis to check, the normal to the segment. It does not matter which of the two possible directions the normal points, as the results will be equivalent as far as the SAT is concerned.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this