Platformer Collision
Moderator: Coders of Rage
- xiphirx
- Chaos Rift Junior
- Posts: 324
- Joined: Mon Mar 22, 2010 3:15 pm
- Current Project: ******** (Unkown for the time being)
- Favorite Gaming Platforms: PC
- Programming Language of Choice: C++
- Contact:
Platformer Collision
I've been working on a platformer for a few weeks now, and it is at the point where I implement collision.
I am currently attempting the bounding box method, and I guess, am successfully detecting the collision, but I am not exactly handling it quite well. I have tried to set the players collision to its previous position, but it creates a bouncing effect. I have also tried setting the players position next to the collision point, but it makes the player stuck pretty much, or it makes it jerky...
I want the collision to behave like cave story's if that helps... any ideas?
if it matters, C++ + SDL
I am currently attempting the bounding box method, and I guess, am successfully detecting the collision, but I am not exactly handling it quite well. I have tried to set the players collision to its previous position, but it creates a bouncing effect. I have also tried setting the players position next to the collision point, but it makes the player stuck pretty much, or it makes it jerky...
I want the collision to behave like cave story's if that helps... any ideas?
if it matters, C++ + SDL
StarCraft II Zerg Strategy, open to all levels of players!
Looking for paid work :< Contact me if you are interested in creating a website, need a web design, or anything else you think I'm capable of
Looking for paid work :< Contact me if you are interested in creating a website, need a web design, or anything else you think I'm capable of
- Bullet Pulse
- Chaos Rift Cool Newbie
- Posts: 89
- Joined: Sun Feb 21, 2010 6:25 pm
Re: Platformer Collision
I'll let you figure out the rest of the code specifically for your platformer, but this should give you a good start.
The function returns a boolean in case you want to play a sound when two things collide, or etc.
Hint: check out the minDist variables.
The function returns a boolean in case you want to play a sound when two things collide, or etc.
Hint: check out the minDist variables.
Code: Select all
bool ExampleClass::IsCollision(SDL_Rect &rectOne, SDL_Rect &rectTwo)
{
SDL_Rect rect1 = rectOne;
SDL_Rect rect2 = rectTwo;
//Find the middle point of each rectangle
rect1.x = (rect1.x * 2 + rect1.w ) / 2;
rect1.y = (rect1.y * 2 + rect1.h ) / 2;
rect2.x = (rect2.x * 2 + rect2.w ) / 2;
rect2.y = (rect2.y * 2 + rect2.h ) / 2;
//Determine overlap for each axis
float xDist = abs(rect1.x - rect2.x);
float yDist = abs(rect1.y - rect2.y);
//minimal amount of distance that the two can be apart and not collide
float xMinDist = (rect1.w + rect2.w) / 2;
float yMinDist = (rect1.h + rect2.h) / 2;
if(xDist >= xMinDist || yDist >= yMinDist)
return false; //neither axis is colliding
float xOverlap = xDist - xMinDist;
float yOverlap = yDist - yMinDist;
//These are the options you have:
if(xOverlap < yOverlap)
//do something
else if(xOverlap > yOverlap)
//do something else
else
//xOverlap and yOverlap are equal so you may want to do something else
return true;
}
Re: Platformer Collision
That's pretty much exact code that Falco posted for collision detection. But if your going to simply use that, xiphirx, you might as well use the improved, and tested code that Falco posted after that. You'll have to search around a bit, but it's the code straight from the Elysian Shadows engine ( or so I'm told).
- Bullet Pulse
- Chaos Rift Cool Newbie
- Posts: 89
- Joined: Sun Feb 21, 2010 6:25 pm
Re: Platformer Collision
Please post the updated code if you can find it
Re: Platformer Collision
Well I have it saved to my hard drive... But I want to check with Falco first, to see if he wants me to repost it...Bullet Pulse wrote:Please post the updated code if you can find it
But I'll go look for the link and edit it in here.
EDIT: Found it - http://elysianshadows.com/phpBB3/viewto ... art=999999
It's also in the Programmer's Education Index that Falco posted (it's stickied if you haven't seen it!)
- xiphirx
- Chaos Rift Junior
- Posts: 324
- Joined: Mon Mar 22, 2010 3:15 pm
- Current Project: ******** (Unkown for the time being)
- Favorite Gaming Platforms: PC
- Programming Language of Choice: C++
- Contact:
Re: Platformer Collision
I'll see how implementing this will turn out...
StarCraft II Zerg Strategy, open to all levels of players!
Looking for paid work :< Contact me if you are interested in creating a website, need a web design, or anything else you think I'm capable of
Looking for paid work :< Contact me if you are interested in creating a website, need a web design, or anything else you think I'm capable of
Re: Platformer Collision
Haha, if you need any help on explaining the code, ask me and I'll do my best to explain it.xiphirx wrote:I'll see how implementing this will turn out...
- xiphirx
- Chaos Rift Junior
- Posts: 324
- Joined: Mon Mar 22, 2010 3:15 pm
- Current Project: ******** (Unkown for the time being)
- Favorite Gaming Platforms: PC
- Programming Language of Choice: C++
- Contact:
Re: Platformer Collision
*sight*, nothing went well, as usual.
I am faced with vectors now. I know a bit about them from a beginning physics course I took 1 years ago now. Vectors have a magnitude and direction, where as a scalar just has magnitude.
So, here is my plan:
- create a vec2d class
- make a function that will get one SDL_Rect (player's bounding box), and generate the second SDL_Rect from the collision map. The function will then determine if they overlap, if they do, create a vector and set its values accordingly. It will return a vector. If the vector has a 0 magnitude, then there was no collision, otherwise, modify the player's coordinates based on the vector.
...
Seems like I'm bound to fail, but it seems like it should work... Here goes..
I am faced with vectors now. I know a bit about them from a beginning physics course I took 1 years ago now. Vectors have a magnitude and direction, where as a scalar just has magnitude.
So, here is my plan:
- create a vec2d class
Code: Select all
class vec2d
{
public:
int mag;
int dirx, diry; //I like slopes more than angels :P
};
...
Seems like I'm bound to fail, but it seems like it should work... Here goes..
StarCraft II Zerg Strategy, open to all levels of players!
Looking for paid work :< Contact me if you are interested in creating a website, need a web design, or anything else you think I'm capable of
Looking for paid work :< Contact me if you are interested in creating a website, need a web design, or anything else you think I'm capable of
- xiphirx
- Chaos Rift Junior
- Posts: 324
- Joined: Mon Mar 22, 2010 3:15 pm
- Current Project: ******** (Unkown for the time being)
- Favorite Gaming Platforms: PC
- Programming Language of Choice: C++
- Contact:
Re: Platformer Collision
Double Post :O!
Ok, here is what I came up with, it doesn't work quite yet :/
vec2d is a class made by me
Maybe someone can help me sort this out? am I supposed to calculate the center of the boxes or something? looking at my algorithm theoretically, it should work right?
Ok, here is what I came up with, it doesn't work quite yet :/
Code: Select all
vec2d Map::checkCollision(SDL_Rect obj)
{
vec2d vector;
vector.dirX = vector.dirY = 0;
vector.mag = 0;
if ( (obj.y/16) >= 0 &&
((obj.y+obj.h)/16) >=0 &&
(obj.x/16) >= 0 &&
((obj.x+obj.w)/16) >=0 &&
(obj.y/16) < data1.numrows() &&
((obj.y+obj.h)/16) < data.numrows() &&
(obj.x/16) < data1.numcols() &&
((obj.x+obj.w)/16) < data.numcols() &&
(
data1[(obj.y/16)][(obj.x/16)] != 0 ||
data1[(obj.y/16)][((obj.x+obj.w)/16)] != 0 ||
data1[((obj.y+obj.h)/16)][(obj.x/16)] != 0 ||
data1[((obj.y+obj.h)/16)][((obj.x+obj.w)/16)] != 0
)
)
{
SDL_Rect tile;
tile.x = (obj.x/16)*16;
tile.y = (obj.y/16)*16;
tile.w = tile.h = 16;
if (
obj.x > tile.x &&
obj.x < (tile.x+tile.w)
)
{
vector.dirX = (tile.x+tile.w)-obj.x;
vector.mag = 1;
}
if (
(obj.x+obj.w) > tile.x &&
(obj.x+obj.w) < (tile.x+tile.w)
)
{
vector.dirX = (obj.x+obj.w) - tile.x;
vector.mag = -1;
}
if (
(obj.y+obj.h) > tile.y &&
(obj.y+obj.h) < (tile.y+tile.h)
)
{
vector.dirY = (obj.y+obj.h) - tile.y;
vector.mag = -1;
}
if (
obj.y < (tile.y+tile.h) &&
obj.y > tile.y
)
{
vector.dirY = (tile.y+tile.h) - obj.y;
vector.mag = 1;
}
}
return vector;
}
Code: Select all
#ifndef VEC2D
#define VEC2D
class vec2d
{
public:
int mag;
int dirX, dirY;
};
#endif
StarCraft II Zerg Strategy, open to all levels of players!
Looking for paid work :< Contact me if you are interested in creating a website, need a web design, or anything else you think I'm capable of
Looking for paid work :< Contact me if you are interested in creating a website, need a web design, or anything else you think I'm capable of
Re: Platformer Collision
Alright, a quick suggestion:
So this is a basic representation of a vector. I noticed you had a magnitude and two integers to represent direction. Also, I'm going to suggest that you use floats or doubles over integers. The numbers won't always be pretty, so you may be losing accuracy with using integers.
Anyways, the x and y represent one end of the vector. The other end is assumed to be (0, 0). So by using the distance formula you can find the distance between (0, 0) and (x, y) - which actually simplifies down to: sqrt(x^2 + y^2). This distance represents the magnitude. The direction of your vector can be found as well by assuming each component to represent the sides of a triangle, and using some geometry.
If you have any questions about that, just let me know =p, hope this post helped haha
Code: Select all
class Vector2D
{
float x;
float y;
float Magnitude();
void Reverse();
void Normalize();
void Reflect(Vector2D& norm);
};
Anyways, the x and y represent one end of the vector. The other end is assumed to be (0, 0). So by using the distance formula you can find the distance between (0, 0) and (x, y) - which actually simplifies down to: sqrt(x^2 + y^2). This distance represents the magnitude. The direction of your vector can be found as well by assuming each component to represent the sides of a triangle, and using some geometry.
If you have any questions about that, just let me know =p, hope this post helped haha
- xiphirx
- Chaos Rift Junior
- Posts: 324
- Joined: Mon Mar 22, 2010 3:15 pm
- Current Project: ******** (Unkown for the time being)
- Favorite Gaming Platforms: PC
- Programming Language of Choice: C++
- Contact:
Re: Platformer Collision
Code: Select all
vec2d Map::checkCollision(SDL_Rect obj)
{
vec2d vector;
vector.dirX = vector.dirY = 0;
vector.mag = 0;
if ( (obj.y/16) >= 0 &&
((obj.y+obj.h)/16) >=0 &&
(obj.x/16) >= 0 &&
((obj.x+obj.w)/16) >=0 &&
(obj.y/16) < data1.numrows() &&
((obj.y+obj.h)/16) < data.numrows() &&
(obj.x/16) < data1.numcols() &&
((obj.x+obj.w)/16) < data.numcols()
)
{
SDL_Rect tile;
tile.x=tile.y=0;
tile.w = tile.h = 16;
if (data1[(obj.y/16)][(obj.x/16)] != 0)
{
tile.x = (obj.x/16)*16;
tile.y = (obj.y/16)*16;
}
else if (data1[(obj.y/16)][((obj.x+obj.w)/16)] != 0)
{
tile.x = ((obj.x+obj.w)/16)*16;
tile.y = (obj.y/16)*16;
}
else if (data1[((obj.y+obj.h)/16)][(obj.x/16)] != 0)
{
tile.x = (obj.x/16)*16;
tile.y = ((obj.y+obj.h)/16)*16;
}
else if (data1[((obj.y+obj.h)/16)][((obj.x+obj.w)/16)] != 0)
{
tile.x = ((obj.x+obj.w)/16)*16;
tile.y = ((obj.y+obj.h)/16)*16;
}
if (
obj.x >= tile.x &&
obj.x <= (tile.x+tile.w)
)
{
vector.dirX = (tile.x+tile.w)-obj.x;
vector.mag = 1;
}
if (
(obj.x+obj.w) >= tile.x &&
(obj.x+obj.w) <= (tile.x+tile.w)
)
{
vector.dirX = (obj.x+obj.w) - tile.x;
vector.mag = -1;
}
if (
(obj.y+obj.h) >= tile.y &&
(obj.y+obj.h) <= (tile.y+tile.h)
)
{
vector.dirY = (obj.y+obj.h) - tile.y;
vector.mag = -1;
}
if (
obj.y <= (tile.y+tile.h) &&
obj.y >= tile.y
)
{
vector.dirY = (tile.y+tile.h) - obj.y;
vector.mag = 1;
}
}
return vector;
}
StarCraft II Zerg Strategy, open to all levels of players!
Looking for paid work :< Contact me if you are interested in creating a website, need a web design, or anything else you think I'm capable of
Looking for paid work :< Contact me if you are interested in creating a website, need a web design, or anything else you think I'm capable of
- xiphirx
- Chaos Rift Junior
- Posts: 324
- Joined: Mon Mar 22, 2010 3:15 pm
- Current Project: ******** (Unkown for the time being)
- Favorite Gaming Platforms: PC
- Programming Language of Choice: C++
- Contact:
Re: Platformer Collision
Still going at it... :/'
Here is the function
and here is handling the result...
I've read the function over about 4 times now... it should work perfectly right? That means the way I'm handling it is wrong... :'/
Here is the function
Code: Select all
vec2d Map::checkCollision(SDL_Rect obj)
{
vec2d vector;
vector.dirX = vector.dirY = 0;
vector.xMag = 0;
vector.yMag = 0;
if ( (obj.y/16) >= 0 &&
((obj.y+obj.h)/16) >=0 &&
(obj.x/16) >= 0 &&
((obj.x+obj.w)/16) >=0 &&
(obj.y/16) < data1.numrows() &&
((obj.y+obj.h)/16) < data.numrows() &&
(obj.x/16) < data1.numcols() &&
((obj.x+obj.w)/16) < data.numcols()
)
{
SDL_Rect tile;
tile.x=tile.y=0;
tile.w = tile.h = 16;
int numy, numx;
char dir;
dir = 'N';
numy = obj.y/16;
numx = obj.x/16;
// TOP LEFT = A
// TOP RIGHT = B
// BOTTOM LEFT = C
// BOTTOM RIGHT = D
// NULL = N
if (data1[numy][numx] != 0)
{
tile.x = numx*16;
tile.y = numy*16;
dir = 'A';
}
if (data1[numy][numx+1] != 0)
{
tile.x = (numx+1)*16;
tile.y = numy*16;
dir = 'B';
}
if (data1[numy+1][numx+1] != 0)
{
tile.x = (numx+1)*16;
tile.y = (numy+1)*16;
dir = 'D';
}
if (data1[numy+1][numx] != 0)
{
tile.x = numx*16;
tile.y = (numy+1)*16;
dir = 'C';
}
if (dir == 'N')
{
return vector; //no collision
}
switch (dir)
{
case 'A': // TOP LEFT
vector.dirX = ((numx*16) + tile.w) - obj.x;
vector.dirY = ((numy*16) + tile.h) - obj.y;
vector.xMag = 1;
vector.yMag = 1;
break;
case 'B': // TOP RIGHT
vector.dirX = (obj.x+obj.w) - tile.x;
vector.dirY = ((numy*16) + tile.h) - obj.y;
vector.xMag = -1;
vector.yMag = 1;
break;
case 'C': // BOTTOM LEFT
vector.dirX = ((numx*16) + tile.w) - obj.x;
vector.dirY = (obj.y+obj.h) - tile.y;
vector.xMag = 1;
vector.yMag = -1;
break;
case 'D': // BOTTOM RIGHT
vector.dirX = (obj.x+obj.w) - tile.x;
vector.dirY = (obj.y+obj.h) - tile.y;
vector.xMag = -1;
vector.yMag = -1;
break;
default:
return vector; // no collision
break;
}
}
return vector;
}
and here is handling the result...
Code: Select all
motion = curMap.checkCollision(boundingBox);
if (motion.xMag != 0 || motion.yMag != 0)
{
switch ( motion.dirX < motion.dirY )
{
case true:
x += motion.dirX * motion.xMag;
xVel=0;
break;
case false:
y += motion.dirY * motion.yMag;
yVel=0;
jumping = false;
break;
default:
break;
}
}
StarCraft II Zerg Strategy, open to all levels of players!
Looking for paid work :< Contact me if you are interested in creating a website, need a web design, or anything else you think I'm capable of
Looking for paid work :< Contact me if you are interested in creating a website, need a web design, or anything else you think I'm capable of