Nick
2004.10.12, 12:56 AM
Seems like collisions are some of the hardest things in programming. I searched the forums a bit and learned some things but none really helped solve my imediate problem. I learned when to use global functions and member functions. I learned various (probably 5) different ways of detecting collisions in both C/C++ and Objective-C. In my collision code, I simply take a side of one box and see if it falls between a side and predetermined distance into another box. Here's a bit of the code:
This code is for a sidescroller I'm making with SDL/OpenGL (though maybe porting to Cocoa/OpenGL). The problem is that with my gravity code there are occasions (not all the time) where the player falls through objects. I'm assuming it's because it's going to fast to detect the collision the way it is.
Note: GetCSide() is a dumb way of calling this. Basically each object can have up to four sides for collisions which are set in an array of member variables. This way some things can have collisions on the top and sides but not the bottom such as some platforms similar to Mario games. TILE_SIZE is simply my defined size for a tile in the game. COLLISION_CUSHION is the defined portion of a tile into the player that is used for collision detection. Everything else should be pretty self explanatory. GetX,Y,Z are for coordinates. GetW,H are for dimensions. Set functions simply set their respective variable
void CheckCollisionPG(Player &p, Ground &g)
{
if (p.GetZ()==g.GetZ()) //if we're on the same z plane
{
for (int i=0; i<=4; i++)
{
switch (g.GetCSide(i))
{
case TOP :
{
if ((p.GetX()+p.GetW()>=g.GetX()) &&
(p.GetX()<=g.GetX()+g.GetW())) //if we're aligned on the Y axis
{
if ((p.GetY()<=(g.GetY()+g.GetH())) &&
((p.GetY()+(COLLISION_CUSHION*TILE_SIZE))>=(g.GetY()+g.GetH())))
{
p.SetY(g.GetY()+g.GetH()+.0001);
p.SetDescent(0);
}
}
break;
}
case BOTTOM :
{
if ((p.GetX()+p.GetW()>=g.GetX()) &&
(p.GetX()<=g.GetX()+g.GetW())) //if we're aligned on the Y axis
{
if ((p.GetY()+p.GetH()>=g.GetY()) &&
(p.GetY()+p.GetH()-(COLLISION_CUSHION*TILE_SIZE)<=g.GetY()))
{
p.SetY(g.GetY()-p.GetH()-.0001);
}
}
break;
}
case LEFT :
{
if ((p.GetY()+p.GetH()>=g.GetY()) &&
(p.GetY()<=g.GetY()+g.GetH())) //if we're aligned on the X axis
{
if ((p.GetX()+p.GetW()>=g.GetX()) &&
(p.GetX()+p.GetW()-(COLLISION_CUSHION*TILE_SIZE)<=g.GetX()))
{
p.SetX(g.GetX()-p.GetW()-.0001);
}
}
break;
}
case RIGHT :
{
if ((p.GetY()+p.GetH()>=g.GetY()) &&
(p.GetY()<=g.GetY()+g.GetH())) //if we're aligned on the X axis
{
if ((p.GetX()<=g.GetX()+g.GetW()) &&
(p.GetX()+(COLLISION_CUSHION*TILE_SIZE)>=g.GetX()+g.GetW()))
{
p.SetX(g.GetX()+g.GetW()+.0001);
}
}
break;
}
}
}
}
}
If anybody can help me fix this efficiently or offer up some C/C++ collision code for a sidescroller, I'd appreciate it.
This code is for a sidescroller I'm making with SDL/OpenGL (though maybe porting to Cocoa/OpenGL). The problem is that with my gravity code there are occasions (not all the time) where the player falls through objects. I'm assuming it's because it's going to fast to detect the collision the way it is.
Note: GetCSide() is a dumb way of calling this. Basically each object can have up to four sides for collisions which are set in an array of member variables. This way some things can have collisions on the top and sides but not the bottom such as some platforms similar to Mario games. TILE_SIZE is simply my defined size for a tile in the game. COLLISION_CUSHION is the defined portion of a tile into the player that is used for collision detection. Everything else should be pretty self explanatory. GetX,Y,Z are for coordinates. GetW,H are for dimensions. Set functions simply set their respective variable
void CheckCollisionPG(Player &p, Ground &g)
{
if (p.GetZ()==g.GetZ()) //if we're on the same z plane
{
for (int i=0; i<=4; i++)
{
switch (g.GetCSide(i))
{
case TOP :
{
if ((p.GetX()+p.GetW()>=g.GetX()) &&
(p.GetX()<=g.GetX()+g.GetW())) //if we're aligned on the Y axis
{
if ((p.GetY()<=(g.GetY()+g.GetH())) &&
((p.GetY()+(COLLISION_CUSHION*TILE_SIZE))>=(g.GetY()+g.GetH())))
{
p.SetY(g.GetY()+g.GetH()+.0001);
p.SetDescent(0);
}
}
break;
}
case BOTTOM :
{
if ((p.GetX()+p.GetW()>=g.GetX()) &&
(p.GetX()<=g.GetX()+g.GetW())) //if we're aligned on the Y axis
{
if ((p.GetY()+p.GetH()>=g.GetY()) &&
(p.GetY()+p.GetH()-(COLLISION_CUSHION*TILE_SIZE)<=g.GetY()))
{
p.SetY(g.GetY()-p.GetH()-.0001);
}
}
break;
}
case LEFT :
{
if ((p.GetY()+p.GetH()>=g.GetY()) &&
(p.GetY()<=g.GetY()+g.GetH())) //if we're aligned on the X axis
{
if ((p.GetX()+p.GetW()>=g.GetX()) &&
(p.GetX()+p.GetW()-(COLLISION_CUSHION*TILE_SIZE)<=g.GetX()))
{
p.SetX(g.GetX()-p.GetW()-.0001);
}
}
break;
}
case RIGHT :
{
if ((p.GetY()+p.GetH()>=g.GetY()) &&
(p.GetY()<=g.GetY()+g.GetH())) //if we're aligned on the X axis
{
if ((p.GetX()<=g.GetX()+g.GetW()) &&
(p.GetX()+(COLLISION_CUSHION*TILE_SIZE)>=g.GetX()+g.GetW()))
{
p.SetX(g.GetX()+g.GetW()+.0001);
}
}
break;
}
}
}
}
}
If anybody can help me fix this efficiently or offer up some C/C++ collision code for a sidescroller, I'd appreciate it.