diff --git a/Shared/Player.cs b/Shared/Player.cs index 93931d8..bbca5cf 100644 --- a/Shared/Player.cs +++ b/Shared/Player.cs @@ -55,11 +55,14 @@ namespace SemiColinGames { // Broad test: remove all collision targets nowhere near the player. var candidates = new List(); - // TODO: This is strictly larger than it needs to be. We could expand only in the actual - // direction of movement. + // Expand the box in the direction of movement. The center is the midpoint of the line + // between the player's current position and their desired movement. The width increases by + // the magnitude of the movement in each direction. We add 1 to each dimension just to be + // sure (the only downside is a small number of false-positive AABBs, which should be + // discarded by later tests anyhow.) Aabb largeBox = new Aabb( - new Vector2(position.X, position.Y), // current player position - new Vector2(halfSize.X + Math.Abs(movement.X), halfSize.Y + Math.Abs(movement.Y))); + new Vector2(position.X + movement.X / 2, position.Y + movement.Y / 2), + new Vector2(halfSize.X + Math.Abs(movement.X) + 1, halfSize.Y + Math.Abs(movement.Y) + 1)); foreach (var box in collisionTargets) { if (box.Intersect(largeBox) != null) { Debug.AddRect(box, Color.Green); diff --git a/Shared/World.cs b/Shared/World.cs index 80b59ed..ce948e7 100644 --- a/Shared/World.cs +++ b/Shared/World.cs @@ -153,14 +153,26 @@ namespace SemiColinGames { } } tiles = tilesList.ToArray(); - collisionTargets = new Aabb[tiles.Length]; + // Because we added tiles from left to right, the collisionTargets are sorted by x-position. + // We maintain this invariant so that it's possible to efficiently find collisionTargets that + // are nearby a given x-position. + collisionTargets = new Aabb[tiles.Length + 2]; + + // Add a synthetic collisionTarget on the left side of the world. + collisionTargets[0] = new Aabb(new Vector2(-1, 0), new Vector2(1, float.MaxValue)); + + // Now add all the normal collisionTargets for every static terrain tile. Vector2 halfSize = new Vector2(TileSize / 2, TileSize / 2); for (int i = 0; i < tiles.Length; i++) { Vector2 center = new Vector2( tiles[i].Position.Left + halfSize.X, tiles[i].Position.Top + halfSize.Y); - collisionTargets[i] = new Aabb(center, halfSize); + collisionTargets[i + 1] = new Aabb(center, halfSize); } + + // Add a final synthetic collisionTarget on the right side of the world. + collisionTargets[tiles.Length + 1] = new Aabb( + new Vector2(Width * TileSize + 1, 0), new Vector2(1, float.MaxValue)); } public void Draw(SpriteBatch spriteBatch, Camera camera) {