I'm extreme new to game development and this is my second project. I’m working on a platform game that expands on the Platformer example provided at the app hub, so far I’ve got parallax scrolling (horizontal and vertical), moving platforms, tight touch controls, double jumps, melee attacks projectiles, and Game State management all working. BUT for the life of me I can’t figure out how to implement sloped tiles. I’ve searched for a ton of tutorials but I can’t find any good ones (by good I mean ones that i can understand). Again I would but grateful for any help that someone could provide.
Here is the code i am using for collisions (I've edit it to try and incorporate the code from the link below but still no luck. it runs but this code still treats the sloped tile as if they were regular tiles:
Edited Code
/// <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;
// Was the player on a ramp last frame?
bool wasOnRamp = isOnRamp;
float dist =
(float)Math.Sqrt
(Math.Pow
(MathHelper.Clamp
(bounds.Center.X - bounds.Left, 0, Tile.Width), 2) +
Math.Pow
(MathHelper.Clamp
(bounds.Bottom - bounds.Bottom, 0, Tile.Height), 2));
float slopeTopLeft =
(bounds.Bottom -
((bounds.Center.X - bounds.Left) *
(float)Math.Sin
(Math.Atan2
(bounds.Height,
(bounds.Center.X - bounds.Left)))));
float slopeTopRight =
(bounds.Bottom -
((bounds.Center.X - bounds.Right) *
(float)Math.Sin
(Math.Atan2
(bounds.Height,
(bounds.Center.X - bounds.Right)))));
// Reset flag to search for ground collision.
isOnGround = false;
isOnRamp = false;
//For each potentially colliding movable tile.
foreach (var movableTile in level.movableTiles)
{
// Reset flag to search for movable tile collision.
movableTile.PlayerIsOn = false;
//check to see if player is on tile.
if ((BoundingRectangle.Bottom >= movableTile.BoundingRectangle.Top) &&
(BoundingRectangle.Left >= movableTile.BoundingRectangle.Left - (BoundingRectangle.Width)) &&
(BoundingRectangle.Right <= movableTile.BoundingRectangle.Right + (BoundingRectangle.Width)))
{
if ((BoundingRectangle.Bottom < movableTile.BoundingRectangle.Top + 5))
{
movableTile.PlayerIsOn = true;
}
}
bounds = HandleCollision(bounds, movableTile.Collision, movableTile.BoundingRectangle);
}
// for (int x = leftTile; x <= rightTile; ++x)
// {
// TileCollision collision = Level.GetCollision(x, bottomTile);
// if (collision == TileCollision.SlantedUp || collision == TileCollision.SlantedDown)
// {
// isOnRamp = true;
// }
// }
// For each potentially colliding tile,
for (int y = topTile; y <= bottomTile; ++y)
{
for (int x = leftTile; x <= rightTile; ++x)
{
// If this tile is collidable,
TileCollision collision = Level.GetCollision(x, y);
/*
if (collision == TileCollision.SlantedUp)
{
//create a rectangle collision box
Rectangle tileCol = Level.GetBounds(x, y); //new Rectangle(x * Tile.Size, (y * Tile.Size), Tile.Size, Tile.Size + 1);
//if player collision "col" collides with "tileCol" and you haven't done this before this itteration (only happens once per full double loop)
if (bounds.Intersects(tileCol) && !isOnRamp)
{
//get the angle of the tile
float angle = level.angle; // [level.tile[x, y]];
//get the x distance of how far away the player's right is inside the tile
float dist = (bounds.X + bounds.Width) - tileCol.X;
//constructs the opposite of a right triangle
float opposite = (float)(Math.Tan(MathHelper.ToRadians(angle)) * (dist));
if (angle < 90)
{
//if player's right is less then or equal to tile's right
if (bounds.X + bounds.Width <= tileCol.X + tileCol.Width)
{
//place player on slope. this works properly
position.Y = tileCol.Y - opposite;
//tell the program we don't wanna go through this again until the next full loop starts.
isOnRamp = true;
}
}
else if (angle > 90)
{
if ((bounds.X + bounds.Width) >= tileCol.X)
{
//this is where the error is. the player goes "up" a slope that's 315 degrees, instead of down it.
//how do I make the player go down the slope that's 315 degrees!?
position.Y = tileCol.Y + opposite;
isOnRamp = true;
}
}
}
}
*/
//If we touched a checkpoint tile, set our new checkpoint here
if (collision == TileCollision.Checkpoint)
level.checkpoint = new Vector2(x, y) * Tile.Size;
if (collision != TileCollision.Passable)
{
float angleInRadians = MathHelper.ToRadians(45);
float m = (float)Math.Sin(angleInRadians) / (float)Math.Cos(angleInRadians);
// Determine collision depth (with direction) and magnitude.
Rectangle tileBounds = Level.GetBounds(x, y);
Vector2 depth = RectangleExtensions.GetIntersectionDepth(bounds, tileBounds);
if (depth != Vector2.Zero)
{
float absDepthX = Math.Abs(depth.X);
float absDepthY = Math.Abs(depth.Y);
// List<TileEdge> collidableEdges = Level.GetCollidableEdges(x, y);
// Resolve the collision along the shallow axis.
if (absDepthY < absDepthX || collision == TileCollision.Platform)
{
// If we crossed the top of a tile, we are on the ground.
if (previousBottom <= tileBounds.Top)
isOnGround = true;
// Ignore platforms, unless we are on the ground.
if (collision == TileCollision.Impassable || IsOnGround)
{
// Resolve the collision along the Y axis.
Position = new Vector2(Position.X, Position.Y + depth.Y);
// Perform further collisions with the new bounds.
bounds = BoundingRectangle;
}
}
else if (collision == TileCollision.Impassable) // Ignore platforms.
{
// Resolve the collision along the X axis.
Position = new Vector2(Position.X + depth.X, Position.Y);
// Perform further collisions with the new bounds.
bounds = BoundingRectangle;
}
else if (collision == TileCollision.SlantedUp)
{
// float dist = (bounds.X + bounds.Width) - depth.X;
// float opposite = (float)(Math.Tan(MathHelper.ToRadians(45)) * (dist));
// float a = Position.X - bottomTile;
//bounds = m * a + absDepth.Y;
// Position = new Vector2(Position.X + depth.X, Position.Y - opposite);
// bounds = BoundingRectangle;
// Resolve the collision along the Y axis.
Position = new Vector2
(Position.X, slopeTopLeft);
Position = new Vector2
((float)Math.Round(Position.X),
(float)Math.Round(Position.Y));
// Perform further collisions with the new bounds.
bounds = BoundingRectangle;
}
}
}
}
}
// Save the new bounds bottom.
previousBottom = bounds.Bottom;
}
private Rectangle HandleCollision(Rectangle bounds, TileCollision collision, Rectangle tileBounds)
{
Vector2 depth = RectangleExtensions.GetIntersectionDepth(bounds, tileBounds);
if (depth != Vector2.Zero)
{
float absDepthX = Math.Abs(depth.X);
float absDepthY = Math.Abs(depth.Y);
// Resolve the collision along the shallow axis.
if (absDepthY < absDepthX || collision == TileCollision.Platform)
{
// If we crossed the top of a tile, we are on the ground.
if (previousBottom <= tileBounds.Top)
isOnGround = true;
// Ignore platforms, unless we are on the ground.
if (collision == TileCollision.Impassable || IsOnGround)
{
// Resolve the collision along the Y axis.
Position = new Vector2(Position.X, Position.Y + depth.Y);
// Perform further collisions with the new bounds.
bounds = BoundingRectangle;
}
}
else if (collision == TileCollision.Impassable) // Ignore platforms.
{
// Resolve the collision along the X axis.
Position = new Vector2(Position.X + depth.X, Position.Y);
// Perform further collisions with the new bounds.
bounds = BoundingRectangle;
}
}
return bounds;
}
I tried to use it but the I can't figure out how to implement it for example:
Does lv = level
Does col = tileBounds
Does pos = Position
Does tileCol = Collision
ETC.
(sorry to be such a noob)
– Nexus1216 Dec 22 '11 at 00:23