Reputation: 3
I know this question might get asked a lot and for that I am sorry. But I have had trouble with collisions in my game for a while and I would like some help.
First off, the game is a 2D Platformer. Each solid is put in a list. I have this code for collision detection which works pretty good for me:
if (player.rectangle.Intersects(rect))
{
player1Collision = true;
colSolid = solid;
colRectangle = rect;
}
if (player1Collision)
{
Vector2 pos = player.position;
Vector2 pLeft = new Vector2(player.BoundingBox.Left, 0);
Vector2 pRight = new Vector2(player.BoundingBox.Right, 0);
Vector2 pTop = new Vector2(0, player.BoundingBox.Top);
Vector2 pBottom = new Vector2(0, player.BoundingBox.Bottom);
Vector2 sLeft = new Vector2(colSolid.BoundingBox.Left, 0);
Vector2 sRight = new Vector2(colSolid.BoundingBox.Right, 0);
Vector2 sTop = new Vector2(0, colSolid.BoundingBox.Top);
Vector2 sBottom = new Vector2(0, colSolid.BoundingBox.Bottom);
if (player.rectangle.Intersects(colRectangle))
{
if (player.velocity.X > 0 && Vector2.Distance(pRight, sLeft) < player.texture.Width / 2)//left
{
player.velocity.X = 0f;
pos.X = colSolid.BoundingBox.Left - player.BoundingBox.Width;
}
else if (player.velocity.X < 0 && Vector2.Distance(pLeft, sRight) < player.texture.Width / 2)//right
{
player.velocity.X = 0f;
pos.X = colSolid.BoundingBox.Right;
}
if (player.velocity.Y > 0 && Vector2.Distance(pBottom, sTop) < player.texture.Height/ 2) //top
{
player.velocity.Y = 0f;
player.gravityOn = false;
pos.Y = colSolid.BoundingBox.Top - player.BoundingBox.Height;
}
else if (player.velocity.Y < 0 && Vector2.Distance(pTop, sBottom) < player.texture.Height / 2)//bottom
{
player.velocity.Y = 0f;
pos.Y = colSolid.BoundingBox.Bottom;
}
player.position = pos;
}
else
{
player.gravitySpeed = 0.15f;
player.gravityOn = true;
}
}
However the problem is that if the player is not intersecting with the rectangle I set the gravity to on, therefore he falls continuously as he collides with the solid and then is put on top to not collide with it. All I need to know is: how can I avoid this? Is there any other way that I could set the gravity to on without the player falling towards the solid continuously, only to be put back on top of the solid to fall again?
Any help is appreciated.
Upvotes: 0
Views: 2042
Reputation: 23
The way I address this problem may not be optimal (in fact I'm sure it probably isn't) but it has worked for me in all my 2D platforming projects so far.
I begin by defining a second rectangle for the sprite class. This rectangle will have the same Width and X coordinate as the main bounding box, but it will be slightly taller (in my case 2 or 3). You will also need to offset it so that the bottom edges of both rectangles are inline, to illustrate:
Rectangle boundingRect = new Rectangle((int)position.X, (int)position.Y, texture.Width, texture.Height);
Rectangle gravityRect = new Rectangle((int)boundingRect.X, (int)boundingRect.Y - 3, texture.Width, texture.Height + 3);
The sprite class also needs a bool to keep track of if the player should be falling. And one to keep track of whether it is solid (which you obviously assign as desired, during initialization).
public bool isGrounded = false;
bool isSolid;
At the top of my Game1 class, I declare 2 ints:
int gravityTotalI = 0;
int gravityCounterI = 0;
When initializing my sprites, I usually add them all to a List. So that I can do this:
foreach (Sprite s in spriteList)
{
if (s.isSolid)
{
gravityTotalI++;
}
}
Now, I use this bit of logic in the Game1 Update Method:
foreach (Sprite s in spriteList)
{
if (!s.Equals(player)
{
if (player.boundingRect.Intersects(s.boundingRect) || player.boundingRect.Intersects(s.gravityRect))
{
player.isGrounded = true;
gravityCounterI = 0;
}
else
{
gravCounterI++;
if (gravCounterI >= gravTotalI)
{
player.isGrounded = false;
gravCounterI = 0;
}
}
if (player.boundingRect.Intersects(s.boundingRect))
{
player.position.Y -= 2f; //set the resistance of the platform here
}
}
} //end of foreach loop.
if (!player.isGrounded)
{
player.position.Y += 2f; //set the force of gravity here.
}
Building a decent directional collision engine is a different thing, but this technique will handle the basics (and get rid of that infernal bouncing).
Hope this isn't too long-winded/doesn't miss out anything important, and I really hope it helps - I struggled with exactly the same problem as you for a long time, and I know how frustrating it can be!
I'm looking forward to seeing others' techniques for handling this!
Upvotes: 1