Platformer Move Left Glitch Fix
I have been trying out code samples on Windows Phone. The platformer game sample moves a player left and right by tilting the phone in the direction to travel. The sample code as published on 10/4/2011 has a problem where the player gets stuck when you tilt to move left until you tilt a lot and he flys over left. This happens because the collision code detects a collision with the ground tile at low speeds. Here is my update for the HandleCollisions() method which avoids the problem.
/// <summary>
/// Detects and resolves all collisions between the player and his neighboring
/// tiles. When a collision is detected, the player is pushed away along one
/// axis to prevent overlapping. There is some special logic for the Y axis to
/// handle platforms which behave differently depending on direction of movement.
/// </summary>
private void HandleCollisions()
{
// Get the player's bounding rectangle and find neighboring tiles.
Rectangle bounds = BoundingRectangle;
int leftTile = (int)Math.Floor((float)bounds.Left / Tile.Width);
int rightTile = (int)Math.Ceiling(((float)bounds.Right / Tile.Width)) - 1;
int topTile = (int)Math.Floor((float)bounds.Top / Tile.Height);
int bottomTile = (int)Math.Ceiling(((float)bounds.Bottom / Tile.Height)) - 1;
// Reset flag to search for ground collision.
isOnGround = false;
// For each potentially colliding tile,
for (int y = topTile; y <= bottomTile; ++y)
{
//
// The y loop checks all tile rows that the player intersects with from top to bottom. The x loop checks
// each tile that the player intersects with on that row depending on the players direction of travel.
// The collision tests are required to go in the direction of travel so as to avoid detecting collisions
// with the platform that the player is running on in the horizontal direction. Instead a ground
// collision will be detected and corrected first in the vertical direction and since the player position
// is moved back up and is no longer in line with the platform when the horizontal collision check occurs.
// This direction of travel identification is only required because the collision correction assumes that
// the axis to bounce the player back is the axis with the smallest overlap. This isn't always 100% true.
//
if (velocity.X < 0)
for (int x = rightTile; x >= leftTile; --x)
HandleTileCollisions(ref bounds, x, y);
else
for (int x = leftTile; x <= rightTile; ++x)
HandleTileCollisions(ref bounds, x, y);
}
// Save the new bounds bottom.
previousBottom = bounds.Bottom;
}
/// <summary>
/// Calcualtes and corrects collisions of the player position with items on the level map. This method identifies the depth of the
/// collision in the x and y axis and moves the player position back to a location that would not overlap with the object it
/// collided with. It does this in the axis with the smallest collision as a guess as to the direction the player should bounce
/// off the object being collided with. This method does a nice job of having common code for collisions regardless of the
/// direction of travel on the axis as one way is +ve and the other is -ve.
/// </summary>
/// <param name="bounds">the bounding rectabgle in pixels for the player sprite as calculated by the GetBoundingRectangle property</param>
/// <param name="x">the x location of the tile on the map in the range 0 - 19</param>
/// <param name="y">the y location of the tile on the map in the range 0 - 14</param>
void HandleTileCollisions(ref Rectangle bounds, int x, int y)
{
// put the code in here from within the for loop in the original HandleCollisions() method
}