Skip to content

Instantly share code, notes, and snippets.

@daseyb
Created November 19, 2013 23:43
Show Gist options
  • Save daseyb/7554644 to your computer and use it in GitHub Desktop.
Save daseyb/7554644 to your computer and use it in GitHub Desktop.
private void CheckMapCollisionUp(float _dt)
{
//Extends of the player in worl coordinates
//Stretched by velocity to prevent tunneling
float bottom = gameObject.collider.AABB.Bottom / 2 + (vel.Y < 0 ? -vel.Y * _dt : 0);
float top = gameObject.collider.AABB.Top / 2 + (vel.Y > 0 ? -vel.Y * _dt : 0);
float left = gameObject.collider.AABB.Left / 2 + (vel.X > 0 ? -vel.X * _dt : 0);
float right = gameObject.collider.AABB.Right / 2 + (vel.X < 0 ? -vel.X * _dt : 0);
//Tiles around the player vertically, with some leeway
Point leftBotMostTile = Map.VectorToCell(new Vector2(left + 10, bottom + 1));
Point rightBotMostTile = Map.VectorToCell(new Vector2(right - 10, bottom + 1));
Point leftTopMostTile = Map.VectorToCell(new Vector2(left + 10, top - 1));
Point rightTopMostTile = Map.VectorToCell(new Vector2(right - 10, top - 1));
//Reset grounded variable, if we don't detect collision we aren't standing on anything
grounded = false;
bool hitTop = false;
float biggestBotOverlap = 0;
float biggestTopOverLap = 0;
for (int x = leftBotMostTile.X; x <= rightBotMostTile.X; x++)
{
for (int y = leftTopMostTile.Y; y <= leftBotMostTile.Y; y++)
{
TileType topTile = world.Map.GetTile(x, y - 1);
TileType tile = world.Map.GetTile(x, y);
TileType botTile = world.Map.GetTile(x, y + 1);
//Check if we are colliding with a horizontal surface
if (tile == TileType.Complete && !(topTile == TileType.Complete && botTile == TileType.Complete))
{
//Is the center of the current tile below the center of the player?
if (y * Map.TileWidth + Map.TileWidth / 2 > Position.Y)
{
grounded = true;
biggestBotOverlap = y * Map.TileHeight - bottom;
}
//Tile is above the center of the player
else
{
hitTop = true;
vel.Y = 0;
biggestTopOverLap = (y + 1) * Map.TileHeight - top;
}
}
}
}
bool hitLeft = false;
bool hitRight = false;
float biggestHorizontalOverlap = 0;
//Get tiles for the horizontal test, already adjusted by vertical collision results
Point topLeftMostTile = Map.VectorToCell(new Vector2(left, top + 1 + biggestTopOverLap));
Point bottomLeftMostTile = Map.VectorToCell(new Vector2(left, bottom - 1 - biggestBotOverlap));
Point topRightMostTile = Map.VectorToCell(new Vector2(right, top + 1 + biggestTopOverLap));
Point bottomRightMostTile = Map.VectorToCell(new Vector2(right, bottom - 1 - biggestBotOverlap));
//Only collide horizontally if we didn't just land on the ground
if (biggestBotOverlap == 0)
{
//Same as before, but this time horizontally
for (int y = topLeftMostTile.Y; y <= bottomLeftMostTile.Y; y++)
{
for (int x = topLeftMostTile.X; x <= topRightMostTile.X; x++)
{
TileType leftTile = world.Map.GetTile(x - 1, y);
TileType tile = world.Map.GetTile(x, y);
TileType rightTile = world.Map.GetTile(x + 1, y);
if (tile == TileType.Complete && !(leftTile == TileType.Complete && rightTile == TileType.Complete))
{
if (x * Map.TileWidth + Map.TileWidth / 2 < Position.X)
{
hitLeft = true;
biggestHorizontalOverlap = (x + 1) * Map.TileWidth - left;
}
else
{
hitRight = true;
biggestHorizontalOverlap = x * Map.TileWidth - right;
}
}
}
}
}
if (biggestHorizontalOverlap != 0 &&
(biggestBotOverlap == 0 && Math.Abs(biggestTopOverLap) < Math.Abs(biggestHorizontalOverlap)))
{
if ((hitLeft && vel.X <= 0) || (hitRight && vel.X >= 0))
{
acc.X = 0;
vel.X = 0;
Position += Vector2.UnitX * biggestHorizontalOverlap;
}
}
else if (biggestBotOverlap != 0 || biggestTopOverLap != 0)
{
if (hitTop)
{
Position += Vector2.UnitY * (biggestTopOverLap + 1);
}
else if (grounded)
{
Position -= Vector2.UnitY * biggestBotOverlap;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment