Well this might not be exactly "basic", It works very nicely and dosen't have any problems because it calculates the X axis and Y axis seperatley, this collision structure will help you later on. (I switched to this from the old Platformer Starter kit code, which was very glitchy)
Assuming you already have methods for gravity, lets get started.
This should be after your falling and velocity logic, It will see what axises need to be checked.
float elapsed = (float)gameTime.ElapsedGameTime.TotalSeconds; //If you havent already, get the elapsed time
if (velocity.X != 0f)
{
Position += velocity.X * Vector2.UnitX * elapsed;
HandleCollisions(CollisionDirection.Horizontal);
}
if (velocity.Y != 0f)
{
Position += velocity.Y * Vector2.UnitY * elapsed;
HandleCollisions(CollisionDirection.Vertical);
}
Now for the very important HandleCollisons method
private void HandleCollisions(CollisionDirection direction)
{
// Get the player's bounding rectangle and find neighboring tiles.
Rectangle bounds = player.GetBoundingBox();
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)
{
for (int x = leftTile; x <= rightTile; ++x)
{
Rectangle tileBounds = Level.GetBounds(x, y);
// If this tile is collidable,
bool IsSolid = map.tiles[x,y].IsSolid;
Vector2 depth;
if (isSolid && TileIntersectsPlayer(BoundingRectangle, tileBounds, direction, out depth))
{
if ((collision == ItemCollision.Platform && movement.Y > 0))
continue;
isOnGround = true;
if (isSolid || isOnGround)
{
if (direction == CollisionDirection.Horizontal)
{
position.X += depth.X;
}
else
{
isOnGround = true;
position.Y += depth.Y;
}
}
}
}
}
// Save the new bounds bottom.
previousBottom = bounds.Bottom;
}
public static bool TileIntersectsPlayer(Rectangle player, Rectangle block, CollisionDirection direction, out Vector2 depth)
{
depth = direction == CollisionDirection.Vertical ? new Vector2(0, player.GetVerticalIntersectionDepth(block)) : new Vector2(player.GetHorizontalIntersectionDepth(block), 0);
return depth.Y != 0 || depth.X != 0;
}
Thats it for that! It will detect collisons, but we need to allow it to figure out how much to push the player back up once it collides! You will need these two extension methods.
public static float GetHorizontalIntersectionDepth(this Rectangle rectA, Rectangle rectB)
{
// Calculate half sizes.
float halfWidthA = rectA.Width / 2.0f;
float halfWidthB = rectB.Width / 2.0f;
// Calculate centers.
float centerA = rectA.Left + halfWidthA;
float centerB = rectB.Left + halfWidthB;
// Calculate current and minimum-non-intersecting distances between centers.
float distanceX = centerA - centerB;
float minDistanceX = halfWidthA + halfWidthB;
// If we are not intersecting at all, return (0, 0).
if (Math.Abs(distanceX) >= minDistanceX)
return 0f;
// Calculate and return intersection depths.
return distanceX > 0 ? minDistanceX - distanceX : -minDistanceX - distanceX;
}
public static float GetVerticalIntersectionDepth(this Rectangle rectA, Rectangle rectB)
{
// Calculate half sizes.
float halfHeightA = rectA.Height / 2.0f;
float halfHeightB = rectB.Height / 2.0f;
// Calculate centers.
float centerA = rectA.Top + halfHeightA;
float centerB = rectB.Top + halfHeightB;
// Calculate current and minimum-non-intersecting distances between centers.
float distanceY = centerA - centerB;
float minDistanceY = halfHeightA + halfHeightB;
// If we are not intersecting at all, return (0, 0).
if (Math.Abs(distanceY) >= minDistanceY)
return 0f;
// Calculate and return intersection depths.
return distanceY > 0 ? minDistanceY - distanceY : -minDistanceY - distanceY;
}
Note you may need to modify this a bit, as the players position is the BOTTOM left. Also a collision enum is needed, for vertical and horizontal. Please tell me if anything seems missing in this.