2d Platform Slope Collision
Moderator: Coders of Rage
-
- Chaos Rift Regular
- Posts: 101
- Joined: Thu Dec 09, 2010 2:13 am
2d Platform Slope Collision
Hey, can someone help me figure out how to calculate collisions for platform slopes, I have basic rect vs rect collision in my game, and i just want some 45 degree slopes.
I've been trying to program it, and have been searching Google non-stop and can't get it to work smoothly enough for my game. I'm no math guru and can use a simple solution, thanks!
I've been trying to program it, and have been searching Google non-stop and can't get it to work smoothly enough for my game. I'm no math guru and can use a simple solution, thanks!
- Ginto8
- ES Beta Backer
- Posts: 1064
- Joined: Tue Jan 06, 2009 4:12 pm
- Programming Language of Choice: C/C++, Java
Re: 2d Platform Slope Collision
Separating Axis theorem. Tutorials here (with fancy pictures) and here (avansc's very nice explanation, with code but only one semi-fancy picture).
Quit procrastinating and make something awesome.
Ducky wrote:Give a man some wood, he'll be warm for the night. Put him on fire and he'll be warm for the rest of his life.
-
- Chaos Rift Regular
- Posts: 101
- Joined: Thu Dec 09, 2010 2:13 am
Re: 2d Platform Slope Collision
Thank you! Both of these links are VERY helpful.
Re: 2d Platform Slope Collision
Just to cut in, I did a Sonic physics engine a while back and with Sonic being famous due to it's slopes, 360 angles, ramps etc you might find this useful:
http://info.sonicretro.org/SPG:Solid_Tiles#Height_Masks
http://info.sonicretro.org/SPG:Solid_Tiles#Height_Masks
Re: 2d Platform Slope Collision
There is no need to use either of those methods for simple 45 degree tile slopes.
How I would do it:
1. Check if player is withing tile boundary box
2. If so, check if relative x >= relative y
How I would do it:
1. Check if player is withing tile boundary box
2. If so, check if relative x >= relative y
- Ginto8
- ES Beta Backer
- Posts: 1064
- Joined: Tue Jan 06, 2009 4:12 pm
- Programming Language of Choice: C/C++, Java
Re: 2d Platform Slope Collision
This is true, but he seemed to think that 45 degree slopes were the minimum he wanted, and if he can do more, I'm all for it.bnpph wrote:There is no need to use either of those methods for simple 45 degree tile slopes.
Quit procrastinating and make something awesome.
Ducky wrote:Give a man some wood, he'll be warm for the night. Put him on fire and he'll be warm for the rest of his life.
Re: 2d Platform Slope Collision
Most definitely yes. But if you're going to add 45 degree slopes, using this method you can add slopes of any degree. Why stop at 5 when the full package is 6?bnpph wrote:There is no need to use either of those methods for simple 45 degree tile slopes.
How I would do it:
1. Check if player is withing tile boundary box
2. If so, check if relative x >= relative y
-
- Chaos Rift Regular
- Posts: 101
- Joined: Thu Dec 09, 2010 2:13 am
Re: 2d Platform Slope Collision
I agree with N64, I'm using the Separating Axis method.
-
- Chaos Rift Regular
- Posts: 101
- Joined: Thu Dec 09, 2010 2:13 am
Re: 2d Platform Slope Collision
I'm using avansc's method for separating axis but something isn't working right. I implemented it like this, but it seems to always return true.
and here is my vector class and rect class
Honestly it's almost copy-pasted with changes may to compile. Can anyone help me see what I'm doing wrong? I implemented the math functions on the vector class myself so they might suck... like i said it seems to return true all the time.
Also ignore the check_x and check_y parameters they aren't used.
Code: Select all
bool Entity::CollisionCheckSAT( int check_x, int check_y, Entity* other )
{
if (other != this)
{
GetBBox()->WorldCoordinates();
other->GetBBox()->WorldCoordinates();
VRect *list[3];
list[0] = GetBBox();
list[1] = other->GetBBox();
list[2] = GetBBox();
Vector2f *p;
float t1;
float t2;
float min;
float max;
for(int i = 0;i < 2;i++)
{
for(int a = 0;a < 2;a++)
{
p = new Vector2f(list[i]->world_coords[a+1]->x - list[i]->world_coords[a]->x, list[i]->world_coords[a+1]->y - list[i]->world_coords[a]->y);
p->Normalize();
t1 = list[i]->world_coords[a]->Projection(p)->Magnitude();
t2 = list[i]->world_coords[a+1]->Projection(p)->Magnitude();
min = std::min(t1, t2);
max = std::max(t1, t2);
float proj[4];
for(int b = 0;b < 4;b++)
{
proj[b] = list[i+1]->world_coords[b]->Projection(p)->Magnitude();
}
if(!this->SATUmbrellas(min, max, proj))
return false;
}
}
return true;
}
}
bool Entity::SATUmbrellas( float min, float max, float proj[] )
{
bool less = false;
bool more = false;
for(int loop = 0;loop < 4;loop++)
{
if(proj[loop] >= min && proj[loop] <= max)
{
return true;
}else if(proj[loop] < min)
{
less = true;
}else if(proj[loop] > max)
{
more = true;
}
}
if(less && more)
return true;
return false;
}
and here is my vector class and rect class
Code: Select all
#include "vector2f.h"
Vector2f::Vector2f()
{
x = 0;
y = 0;
}
Vector2f::Vector2f( float new_x, float new_y )
{
x = new_x;
y = new_y;
}
Vector2f::~Vector2f()
{
}
void Vector2f::Normalize()
{
float mag = Magnitude();
x = x/mag;
y = y/mag;
}
float Vector2f::Magnitude()
{
return sqrt( (x*x)+ (y*y) );
}
float Vector2f::DotProduct( Vector2f* vect )
{
return (x * vect->x + y * vect->y);
}
Vector2f* Vector2f::Projection( Vector2f* vect )
{
Vector2f projected;
projected.x = DotProduct( vect ) / vect->x / (vect->Magnitude()*vect->Magnitude());
projected.y = DotProduct( vect ) / vect->y / (vect->Magnitude()*vect->Magnitude());
return &projected;
}
#include "vrect.h"
VRect::VRect()
{
center = new Vector2f( 0, 0 );
w = 32;
h = 32;
ang = 0;
}
VRect::VRect( float new_x, float new_y, float new_w, float new_h )
{
center = new Vector2f( new_x, new_y );
w = new_w;
h = new_h;
ang = 0;
}
void VRect::WorldCoordinates()
{
float deg = this->ang/180*PI;
this->world_coords[0] = new Vector2f((cos(deg) * -this->w - sin(deg) * -this->h)+this->center->x,
(sin(deg) * -this->w + cos(deg) * -this->h)+this->center->y);
this->world_coords[1] = new Vector2f((cos(deg) * -this->w - sin(deg) * this->h)+this->center->x,
(sin(deg) * -this->w + cos(deg) * this->h)+this->center->y);
this->world_coords[2] = new Vector2f((cos(deg) * this->w - sin(deg) * this->h)+this->center->x,
(sin(deg) * this->w + cos(deg) * this->h)+this->center->y);
this->world_coords[3] = new Vector2f((cos(deg) * this->w - sin(deg) * -this->h)+this->center->x,
(sin(deg) * this->w + cos(deg) * -this->h)+this->center->y);
}
Honestly it's almost copy-pasted with changes may to compile. Can anyone help me see what I'm doing wrong? I implemented the math functions on the vector class myself so they might suck... like i said it seems to return true all the time.
Also ignore the check_x and check_y parameters they aren't used.
Re: 2d Platform Slope Collision
That method works with any right-triangle as long as you scale it properly. Separating axis is for polygonal meshes - most platformers aren't polygon-based.N64vSNES wrote:Most definitely yes. But if you're going to add 45 degree slopes, using this method you can add slopes of any degree. Why stop at 5 when the full package is 6?bnpph wrote:There is no need to use either of those methods for simple 45 degree tile slopes.
How I would do it:
1. Check if player is withing tile boundary box
2. If so, check if relative x >= relative y
Re: 2d Platform Slope Collision
Wow wow dude I'm not suggesting separating axis.bnpph wrote:That method works with any right-triangle as long as you scale it properly. Separating axis is for polygonal meshes - most platformers aren't polygon-based.N64vSNES wrote:Most definitely yes. But if you're going to add 45 degree slopes, using this method you can add slopes of any degree. Why stop at 5 when the full package is 6?bnpph wrote:There is no need to use either of those methods for simple 45 degree tile slopes.
How I would do it:
1. Check if player is withing tile boundary box
2. If so, check if relative x >= relative y
And I'll take your word for it if your method is a simpler way. I'm just putting my own suggestion forward
-
- Chaos Rift Regular
- Posts: 101
- Joined: Thu Dec 09, 2010 2:13 am
Re: 2d Platform Slope Collision
What is the method for doing it without SAT, I'd like to know both.
- Falco Girgis
- Elysian Shadows Team
- Posts: 10294
- Joined: Thu May 20, 2004 2:04 pm
- Current Project: Elysian Shadows
- Favorite Gaming Platforms: Dreamcast, SNES, NES
- Programming Language of Choice: C/++
- Location: Studio Vorbis, AL
- Contact:
Re: 2d Platform Slope Collision
I haven't actually sat down and looked at your algorithm, but something really caught my eye:
I really, REALLY hope you aren't dynamically allocating the world coordinates with new each frame. Why isn't that a stack array of four Vector2's, since you will only ever have four? Not only is this terribly slow each frame, but I don't see where you are even calling delete[] to free the memory.
MEMORY LEAK ALERT!
Code: Select all
void VRect::WorldCoordinates()
{
float deg = this->ang/180*PI;
this->world_coords[0] = new Vector2f((cos(deg) * -this->w - sin(deg) * -this->h)+this->center->x,
(sin(deg) * -this->w + cos(deg) * -this->h)+this->center->y);
this->world_coords[1] = new Vector2f((cos(deg) * -this->w - sin(deg) * this->h)+this->center->x,
(sin(deg) * -this->w + cos(deg) * this->h)+this->center->y);
this->world_coords[2] = new Vector2f((cos(deg) * this->w - sin(deg) * this->h)+this->center->x,
(sin(deg) * this->w + cos(deg) * this->h)+this->center->y);
this->world_coords[3] = new Vector2f((cos(deg) * this->w - sin(deg) * -this->h)+this->center->x,
(sin(deg) * this->w + cos(deg) * -this->h)+this->center->y);
}
MEMORY LEAK ALERT!
-
- Chaos Rift Regular
- Posts: 101
- Joined: Thu Dec 09, 2010 2:13 am
Re: 2d Platform Slope Collision
At the moment it isn't suppose to be any sort of fast, I just want to get it to work first lol.
- Falco Girgis
- Elysian Shadows Team
- Posts: 10294
- Joined: Thu May 20, 2004 2:04 pm
- Current Project: Elysian Shadows
- Favorite Gaming Platforms: Dreamcast, SNES, NES
- Programming Language of Choice: C/++
- Location: Studio Vorbis, AL
- Contact:
Re: 2d Platform Slope Collision
This isn't a matter of speed, optimization, or design. This is a matter of you're committing an unforgivable C/++ crime.like80ninjas wrote:At the moment it isn't suppose to be any sort of fast, I just want to get it to work first lol.
You're leaking 256 bytes of memory every frame.
How much harder would it be to change that array of pointers to just an array and not call new? It would be even easier.
You don't happen to come from a C#/Java background, do you?