diff --git a/BoundingBox.cs b/BoundingBox.cs index 3c2afb7..a1853fb 100644 --- a/BoundingBox.cs +++ b/BoundingBox.cs @@ -5,17 +5,17 @@ namespace LunaLightXMG public class BoundingBox { public Rectangle Bounds { get; private set; } - + public BoundingBox(Rectangle bounds) { Bounds = bounds; } - + public bool Intersects(BoundingBox other) { return Bounds.Intersects(other.Bounds); } - + public void Update(Vector2 position, int width, int height) { Bounds = new Rectangle((int)position.X, (int)position.Y, width, height); diff --git a/CollisionManager.cs b/CollisionManager.cs index 820fc57..08dcb10 100644 --- a/CollisionManager.cs +++ b/CollisionManager.cs @@ -33,13 +33,47 @@ namespace LunaLightXMG } // Method to check if a position is colliding with any wall - public static bool WallCheck(Vector2 position, BoundingBox boundingBox, Platform[] platforms) + public static bool WallCheck(Vector2 position, BoundingBox boundingBox, Platform[] platform) { - if (IsColliding(position + new Vector2(1, 0), boundingBox, platforms) || IsColliding(position + new Vector2(-1, 0), boundingBox, platforms)) + if (IsColliding(position + new Vector2(1, 0), boundingBox, platform) || IsColliding(position + new Vector2(-1, 0), boundingBox, platform)) { return true; } return false; } + + // Method to get the collision side + public enum CollisionSide + { + None, + Top, + Bottom, + Left, + Right + } + + public static CollisionSide GetCollisionSide(Vector2 position, BoundingBox boundingBox, Platform[] platform) + { + if (IsColliding(position + new Vector2(-1, 0), boundingBox, platform)) + { + return CollisionSide.Left; + } + else if (IsColliding(position + new Vector2(1, 0), boundingBox, platform)) + { + return CollisionSide.Right; + } + else if (IsColliding(position + new Vector2(0, -1), boundingBox, platform)) + { + return CollisionSide.Top; + } + else if (IsColliding(position + new Vector2(0, 1), boundingBox, platform)) + { + return CollisionSide.Bottom; + } + else + { + return CollisionSide.None; + } + } } } diff --git a/LunaLightGame.cs b/LunaLightGame.cs index 3d8da90..e30b4e1 100644 --- a/LunaLightGame.cs +++ b/LunaLightGame.cs @@ -105,13 +105,13 @@ namespace LunaLightXMG sinkBeats = Content.Load("music/sinkBeats"); // load player sprite player.LoadContent(Content); // player sprite is now handled in player.cs - + // Spawn 10 enemies at the start of the level enemies = SpawnEnemies(numOfEnemies); - + // Test Render Target Handler renderHandler = new RenderHandler(GraphicsDevice, spriteBatch, retroWidth, retroHeight); - + // Debugging debugFont = Content.Load("fonts/debugFont"); debugGrid = Content.Load("debugGrid"); @@ -224,10 +224,12 @@ namespace LunaLightXMG spriteBatch.DrawString(debugFont, $"VSP: {player.vsp}", new Vector2(10, 10), Color.White); spriteBatch.DrawString(debugFont, $"Grounded: {player.grounded}", new Vector2(10, 30), Color.White); spriteBatch.DrawString(debugFont, $"Walled: {player.walled}", new Vector2(10, 50), Color.White); - spriteBatch.DrawString(debugFont, $"Position: {player.position}", new Vector2(10, 70), Color.White); - spriteBatch.DrawString(debugFont, $"Camera Position: {camera2D.Position}", new Vector2(10, 90), Color.White); - spriteBatch.DrawString(debugFont, $"Camera Rotation: {camera2D.Rotation}", new Vector2(10, 110), Color.White); - spriteBatch.DrawString(debugFont, $"Render Target Zoom: {renderHandler.ZoomLevel}", new Vector2(10, 130), Color.White); + spriteBatch.DrawString(debugFont, $"Collision Side: {player.collisionSide}", new Vector2(10, 70), Color.White); + + spriteBatch.DrawString(debugFont, $"Position: {player.position}", new Vector2(10, 90), Color.White); + spriteBatch.DrawString(debugFont, $"Camera Position: {camera2D.Position}", new Vector2(10, 110), Color.White); + spriteBatch.DrawString(debugFont, $"Camera Rotation: {camera2D.Rotation}", new Vector2(10, 130), Color.White); + spriteBatch.DrawString(debugFont, $"Render Target Zoom: {renderHandler.ZoomLevel}", new Vector2(10, 150), Color.White); spriteBatch.DrawString(debugFont, $"Camera Rotation Control - Rotate left: K, Rotate right: L", new Vector2(10, 190), Color.White); diff --git a/Player.cs b/Player.cs index 0955fc6..18a2fe6 100644 --- a/Player.cs +++ b/Player.cs @@ -27,8 +27,11 @@ namespace LunaLightXMG private Texture2D texture; public Vector2 position; public BoundingBox boundingBox { get; private set; } + public CollisionManager.CollisionSide collisionSide { get; private set; } private CollisionManager collisionManager; + + public Player(Vector2 initPosition) { hsp = 0; @@ -130,7 +133,7 @@ namespace LunaLightXMG hsp = 0; } position.X += hsp; // Horizontal move - + // Vertical collision prediction float onePixv = Math.Sign(vsp); if (CollisionManager.IsColliding(position + new Vector2(0, vsp), boundingBox, platforms)) @@ -150,6 +153,8 @@ namespace LunaLightXMG walled = CollisionManager.WallCheck(position, boundingBox, platforms); if (walled) wasWalled = walled; + + collisionSide = CollisionManager.GetCollisionSide(position, boundingBox, platforms); } private float Approach(float start, float end, float shift) @@ -168,17 +173,26 @@ namespace LunaLightXMG } return start; } - + private void DumpFractions() { if (grounded) { - float adjustedPosX = (float)Math.Round(position.X); - float adjustedPosY = (float)Math.Round(position.Y); - position.X = adjustedPosX; - position.Y = adjustedPosY; + if (collisionSide == CollisionManager.CollisionSide.Right) + { + position.X = (float)Math.Floor(position.X); + } + else if (collisionSide == CollisionManager.CollisionSide.Left) + { + position.X = (float)Math.Ceiling(position.X); + } + else + { + position.X = (float)Math.Round(position.X); + } + position.Y = (float)Math.Round(position.Y); } - + if (vsp >= 0) { hsp += hsp_frac; diff --git a/UpdateNotes/Bugs.md b/UpdateNotes/Bugs.md new file mode 100644 index 0000000..9057a46 --- /dev/null +++ b/UpdateNotes/Bugs.md @@ -0,0 +1,21 @@ +## Stuck in the wall.. - April 13th, 2025 + +**Description:** + +When the playerjumps and moves to the right into a wall, slides down the wall and hits the ground, the player then gets stuck one pixel into the wall. + +**Likely Cause:** + +Our players movement is calculated as floating point values for smooth movement, however to ensure pixel perfect rendering we most round the player position to an integer value when the player stops. + +When the player jumps into a wall to the right the player x position stops at a floating point value and then rounds to the nearest integer once the player hits the ground. This can lead to the player position being rounded into the wall. + +**Possible Fix:** + +Detect which side of the player bounding box is hitting the wall, e.g. left or right and decide to round up or down depending on the side. + +**Fixed:** + +Added a new method to the collision manager that gets the side of the players bounding box that hits a wall. We can use this to decide whther we need to round up or down when cleaning up player position values. + +I also added logic to get top, bottom and none for future things.. \ No newline at end of file