```1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 ``` ```public static class RectangleExtensions { 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; } } public enum Direction { Horizontal, Vertical } public void HandleInput(float elapsed) { KeyboardState state = Keyboard.GetState(); // Handle Keyboard Input int horizontal = state.IsKeyDown(Keys.Left) ? -1 : (state.IsKeyDown(Keys.Right) ? 1 : 0); int vertical = state.IsKeyDown(Keys.Up) ? -1 : (state.IsKeyDown(Keys.Down) ? 1 : 2); // Handle Horizontal Movement if (horizontal != 0) { _playerPosition += Vector2.UnitX * Math.Min(PlayerSpeed * elapsed, Math.Min(_playerSize.X, TileSize)) * horizontal; _playerPosition = new Vector2((float)Math.Round(_playerPosition.X), _playerPosition.Y); HandleCollisions(Direction.Horizontal); } // Handle Vertical Movement if(vertical != 0) { _playerPosition += Vector2.UnitY * Math.Min(PlayerSpeed * elapsed, Math.Min(_playerSize.Y, TileSize)) * vertical; _playerPosition = new Vector2(_playerPosition.X, (float)Math.Round(_playerPosition.Y)); HandleCollisions(Direction.Vertical); } } private void HandleCollisions(Direction direction) { Rectangle playerBounds = GetPlayerBounds(); int leftTile = playerBounds.Left / TileSize; int topTile = playerBounds.Top / TileSize; int rightTile = (int)Math.Ceiling((float)playerBounds.Right / TileSize) - 1; int bottomTile = (int)Math.Ceiling(((float)playerBounds.Bottom / TileSize)) - 1; for (int y = topTile; y <= bottomTile; ++y) { for (int x = leftTile; x <= rightTile; ++x) { Vector2 depth; if (TileIsObstacle(x, y) && TileIntersectsPlayer(playerBounds, GetTileBounds(y, x), direction, out depth)) { _playerPosition += depth; playerBounds = GetPlayerBounds(); } } } } private static Rectangle GetTileBounds(int y, int x) { return new Rectangle(x * TileSize, y * TileSize, TileSize, TileSize); } public Rectangle GetPlayerBounds() { return new Rectangle((int)Math.Round(_playerPosition.X), (int)Math.Round(_playerPosition.Y), (int)Math.Round(_playerSize.X), (int)Math.Round(_playerSize.Y)); } private static bool TileIntersectsPlayer(Rectangle player, Rectangle block, Direction direction, out Vector2 depth) { depth = direction == Direction.Vertical ? new Vector2(0, player.GetVerticalIntersectionDepth(block)) : new Vector2(player.GetHorizontalIntersectionDepth(block), 0); return depth.Y != 0 || depth.X != 0; } private bool TileIsObstacle(int x, int y) { if (x < 0 || y < 0 || x >= _width || y >= _height) return true; return _blocks[x, y] != ' '; } ```