The first problem where the collisions were handled wrong, were solved with this solution posted by David. Instead of solving the two axis at the same time, the solution solves each axis individually. So, instead of sum the velocity at the position and handle the collisions, I sum each velocity and handle the direction:
if (_velocity.Y != 0f)
{
Position += _velocity.Y * Vector2.UnitY * elapsed;
Position = new Vector2(Position.X, (float)Math.Round(Position.Y));
HandleCollisions(Direction.Vertical);
}
if (_velocity.X != 0f)
{
Position += _velocity.X * Vector2.UnitX * elapsed;
Position = new Vector2((float)Math.Round(Position.X), Position.Y);
HandleCollisions(Direction.Horizontal);
}
To solve the second problem, I need manage a way to make the one-way platformers (the ones where you can jump from bottom but stop if falls from top). To resolve this, I made just like the XNA Platformer Demo. On the begin of HandleCollisions()
, I reseted the _isOnGround
variable to false
, so at the beggin of verification the player is not on the ground.
If the tile collision that is being verified through the loop is not passable and the player is intersecting it, verify if the tile collision is a Platform, if the movement is vertical (because the one-way platforms ignores the x axis), and if the previous bottom of the player is less or equal of the tile top:
if (collision == TileCollision.Platform && direction == Direction.Vertical && previousBottom <= tileBounds.Top)
{
_isOnGround = true;
}
If so, the player is on the ground, setting _isOnGround
to true
. After that, I check if the tile collision is a block, if is, the player needs be pushed out from the tile, but I also verify if the player is on the ground, that means he landed on a platform, so he also need be pushed out.
if (collision == TileCollision.Block || (direction == Direction.Vertical && _isOnGround))
{
Position += depth;
playerBounds = BoundingRectangle;
}
Before the end of the method, I set previousBottom = playerBounds.Bottom;
, to prepare for the next update
loop.