Jump to content
  • Advertisement
Sign in to follow this  
Diirewolf

Simple collision detection for sidescroller

This topic is 4248 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

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
Advertisement
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
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
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
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
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
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
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
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
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!