// Check if an exact coordinate has a Blocking Square (Ground, BlockTile, HorizontalWall, etc.) public static bool IsBlockingCoord(TilemapLevel tilemap, int posX, int posY, DirCardinal dir) { short gridX = (short)(posX / (byte)TilemapEnum.TileWidth); short gridY = (short)(posY / (byte)TilemapEnum.TileHeight); return(CollideTile.IsBlockingSquare(tilemap, gridX, gridY, dir)); }
private void RunTickForObjectGroup(Dictionary <int, GameObject> objectGroup) { // Loop through each object in the dictionary, run it's tick: foreach (var obj in objectGroup) { obj.Value.RunTick(); // Run Tile Detection for the Object CollideTile.RunTileCollision(obj.Value); } }
// Identical to "RunTickForObjectGroup", but with an extra overlap test for Characters. // RunTileCollision only detects what you're moving INTO, not what you're on top of. // Characters need the additional check to know what they're on top of, such as for Chests, Doors, NPCs, etc. private void RunTickForCharacterGroup(Dictionary <int, GameObject> objectGroup) { foreach (var obj in objectGroup) { Character character = (Character)obj.Value; // If the character is frozen from a reset, prevent them from running any actions. if (character.frozenFrame >= Systems.timer.Frame) { // If we're on the release frame, provide a sound: if (character.frozenFrame == Systems.timer.Frame) { character.room.PlaySound(Systems.sounds.pop, 0.7f, Systems.camera.posX + Systems.camera.halfWidth, Systems.camera.posY + Systems.camera.halfHeight); } continue; } character.RunTick(); CollideTile.RunTileCollision(character); // Determine Tiles Potentially Touched short gridX = character.GridX; short gridY = character.GridY; short gridX2 = character.GridX2; short gridY2 = character.GridY2; // Run Collision Tests on any tiles beneath the Character (to identify Chests, Doors, NPCs, etc). CollideTile.RunGridTest(character, gridX, gridY, DirCardinal.Center); if (gridX != gridX2) { CollideTile.RunGridTest(character, gridX2, gridY, DirCardinal.Center); if (gridY != gridY2) { CollideTile.RunGridTest(character, gridX, gridY2, DirCardinal.Center); CollideTile.RunGridTest(character, gridX2, gridY2, DirCardinal.Center); } } else if (gridY != gridY2) { CollideTile.RunGridTest(character, gridX, gridY2, DirCardinal.Center); } } }
// Detect interactions with 4 Grid Squares, with object's X,Y in the Top-Left square. public static void RunTileCollision(GameObject actor) { // Don't run collision if the actor is designated not to collide. if (actor.CollideVal <= CollideEnum.NoTileCollide) { return; } // Determine Tiles Potentially Touched short gridX = actor.GridX; short gridY = actor.GridY; short gridX2 = actor.GridX2; short gridY2 = actor.GridY2; bool vertOnly = gridX == gridX2; // If the object is only interacting with vertical squares: if (vertOnly) { if (actor.physics.velocity.Y < 0) { CollideTile.RunGridTest(actor, gridX, gridY, DirCardinal.Up); } else { CollideTile.RunGridTest(actor, gridX, gridY2, DirCardinal.Down); } return; } bool horOnly = gridY == gridY2; // If the object is only interacting between two tiles (left and right). if (horOnly) { if (actor.physics.velocity.X >= 0) { CollideTile.RunGridTest(actor, gridX2, gridY, DirCardinal.Right); } else { CollideTile.RunGridTest(actor, gridX, gridY, DirCardinal.Left); } return; } // If the object is interacting with all four tiles (Top-Left to Bottom-Right). FInt velX = actor.physics.velocity.X; FInt velY = actor.physics.velocity.Y; // If moving downward: if (velY > 0) { // If moving DOWN-RIGHT. if (velX > 0) { // Compare against BOTTOM-LEFT (vs. up) and TOP-RIGHT (vs. left) bool down = CollideTile.RunGridTest(actor, gridX, gridY2, DirCardinal.Down); bool right = CollideTile.RunGridTest(actor, gridX2, gridY, DirCardinal.Right); // Test against corner if neither of the above collided. Direction of collision based on momentum. if (!down && !right) { int yOverlap = actor.posY + actor.bounds.Bottom - (gridY2 * (byte)TilemapEnum.TileHeight); // Returns POSITIVE value if (yOverlap > velY.RoundInt) { CollideTile.RunGridTest(actor, gridX2, gridY2, DirCardinal.Right); return; } int xOverlap = actor.posX + actor.bounds.Right - (gridX2 * (byte)TilemapEnum.TileWidth); // Returns POSITIVE value if (xOverlap > velX.RoundInt) { CollideTile.RunGridTest(actor, gridX2, gridY2, DirCardinal.Down); } } } // If moving DOWN-LEFT: else if (velX < 0) { // Compare against BOTTOM-RIGHT (vs.up) and TOP-LEFT (vs. right) bool down = CollideTile.RunGridTest(actor, gridX2, gridY2, DirCardinal.Down); bool left = CollideTile.RunGridTest(actor, gridX, gridY, DirCardinal.Left); // Test against corner if neither of the above collided. Direction of collision based on momentum. if (!down && !left) { int yOverlap = actor.posY + actor.bounds.Bottom - (gridY2 * (byte)TilemapEnum.TileHeight); // Returns POSITIVE value if (yOverlap > velY.RoundInt) { CollideTile.RunGridTest(actor, gridX, gridY2, DirCardinal.Left); return; } int xOverlap = actor.posX + actor.bounds.Left - (gridX2 * (byte)TilemapEnum.TileWidth); // Returns NEGATIVE value if (xOverlap < velX.RoundInt) { CollideTile.RunGridTest(actor, gridX, gridY2, DirCardinal.Down); } } } // If moving DOWN: else { // Get Overlaps int xOverlapLeft = actor.posX + actor.bounds.Left - (gridX2 * (byte)TilemapEnum.TileWidth); int xOverlapRight = actor.posX + actor.bounds.Right - (gridX2 * (byte)TilemapEnum.TileWidth); // Compare against BOTTOM HALF (vs. up). No corner test. if (xOverlapLeft < 0) { CollideTile.RunGridTest(actor, gridX, gridY2, DirCardinal.Down); } if (xOverlapRight > 0) { CollideTile.RunGridTest(actor, gridX2, gridY2, DirCardinal.Down); } } } // If moving upward: else { // If moving UP-RIGHT: if (velX > 0) { // Compare against TOP-LEFT (vs. down) and BOTTOM-RIGHT (vs. left) bool up = CollideTile.RunGridTest(actor, gridX, gridY, DirCardinal.Up); bool right = CollideTile.RunGridTest(actor, gridX2, gridY2, DirCardinal.Right); // Test against corner if neither of the above collided. Direction of collision based on momentum. if (!up && !right) { int yOverlap = actor.posY + actor.bounds.Top - (gridY2 * (byte)TilemapEnum.TileHeight); // Returns NEGATIVE value if (yOverlap < velY.RoundInt) { CollideTile.RunGridTest(actor, gridX2, gridY, DirCardinal.Right); return; } int xOverlap = actor.posX + actor.bounds.Right - (gridX2 * (byte)TilemapEnum.TileWidth); // Returns POSITIVE value if (xOverlap > velX.RoundInt) { CollideTile.RunGridTest(actor, gridX2, gridY, DirCardinal.Up); } } } // If moving UP-LEFT: else if (velX < 0) { // Compare against TOP-RIGHT (vs. down) and BOTTOM-LEFT (vs. right) bool up = CollideTile.RunGridTest(actor, gridX2, gridY, DirCardinal.Up); bool left = CollideTile.RunGridTest(actor, gridX, gridY2, DirCardinal.Left); // Test against corner if neither of the above collided. Direction of collision based on momentum. if (!up && !left) { int yOverlap = actor.posY + actor.bounds.Top - (gridY2 * (byte)TilemapEnum.TileHeight); // Returns NEGATIVE value if (yOverlap < velY.RoundInt) { CollideTile.RunGridTest(actor, gridX, gridY, DirCardinal.Left); return; } int xOverlap = actor.posX + actor.bounds.Left - (gridX2 * (byte)TilemapEnum.TileWidth); // Returns NEGATIVE value if (xOverlap < velX.RoundInt) { CollideTile.RunGridTest(actor, gridX, gridY, DirCardinal.Up); } } } // If moving UP: else { // Get Overlaps int xOverlapLeft = actor.posX + actor.bounds.Left - (gridX2 * (byte)TilemapEnum.TileWidth); int xOverlapRight = actor.posX + actor.bounds.Right - (gridX2 * (byte)TilemapEnum.TileWidth); // Compare against TOP HALF (vs. down). No corner test. if (xOverlapLeft < 0) { CollideTile.RunGridTest(actor, gridX, gridY, DirCardinal.Up); } if (xOverlapRight > 0) { CollideTile.RunGridTest(actor, gridX2, gridY, DirCardinal.Up); } } } }