/// <summary> /// Instantiates a player, puts him in the level, and remembers where to put him when he is resurrected. /// </summary> private Tile LoadStartTile(int x, int y) { if (Player != null) { throw new NotSupportedException("A level may only have one starting point."); } start = RectangleExtensions.GetBottomCenter(GetTileBounds(x, y)); Player = new Byakuya(this, start, graphicsDevice); return(new Tile(null, TileCollision.Passable)); }
/// <summary> /// This is to handle tunneling from dashes. Considers the dash direction. /// </summary> protected void HandleDashCollisions() { // 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 x = leftTile; x <= rightTile; ++x) { for (int y = topTile; y <= bottomTile; ++y) { // If this tile is collidable, TileCollision collision = level.GetCollision(x, y); if (collision == TileCollision.Impassable) // only cannot dash through impassable blocks { // Determine collision depth (with direction) and magnitude. Rectangle tileBounds = level.GetTileBounds(x, y); int dashDirection = 0; if (dashState == DashState.dashLeft) { dashDirection = 1; } else if (dashState == DashState.dashRight) { dashDirection = 2; } else if (dashState == DashState.dashUp) { dashDirection = 3; } else if (dashState == DashState.dashDown) { dashDirection = 4; } Vector2 depth = RectangleExtensions.GetDashIntersectionDepth(bounds, tileBounds, dashDirection); if (depth != Vector2.Zero) { float absDepthY = depth.Y; // GetDashIntersectionDepth should always return positive values float absDepthX = depth.X; // GetDashIntersectionDepth should always return positive values // Dash downwards if (dashState == DashState.dashDown) { // If we crossed the top of a tile, we are on the ground. if (previousBottom <= tileBounds.Top) { isOnGround = true; } // Offset upwards position = new Vector2(position.X, position.Y - absDepthY); } // Dash upwards else if (dashState == DashState.dashUp) { // Offset downwards position = new Vector2(position.X, position.Y + absDepthY); } // Dash right else if (dashState == DashState.dashRight) { // Offset left position = new Vector2(position.X - absDepthX, position.Y); } // Dash left else if (dashState == DashState.dashLeft) { // Offset right. position = new Vector2(position.X + absDepthX, position.Y); } // Perform further collisions with the new bounds. bounds = BoundingRectangle; } } } } // Save the new bounds bottom. previousBottom = bounds.Bottom; }
/// <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> protected 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) { for (int x = leftTile; x <= rightTile; ++x) { // If this tile is collidable, TileCollision collision = level.GetCollision(x, y); if (collision != TileCollision.Passable) { // Determine collision depth (with direction) and magnitude. Rectangle tileBounds = level.GetTileBounds(x, y); 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; } } } } } // Save the new bounds bottom. previousBottom = bounds.Bottom; }