/// <summary> /// This code tries to extend the collision tile to the largest possible rectangle (eg find the complete obstacle), /// so that following algorithm parts /// can work with these rectangles to easily decide whether to move the offending entity on the x or the y axis. /// </summary> /// <param name="collider">The collider to work with, probably the grid collision collider.</param> /// <param name="startX">int x position of the tile in the grid (!= pixel position)</param> /// <param name="startY">int y position of the tile in the grid (!= pixel position)</param> /// <returns></returns> public static Rectangle ExtendCollisionTile(GridCollider collider, int startX, int startY) { //copy the positions into variables that will be changed to calculate the resulting rectangle int left = startX, right = startX + 1, top = startY, bottom = startY + 1; //go as far in all directions as the tile is collidable while (collider.GetTile(left - 1, startY) && left > 1) { left--; } while (collider.GetTile(right, startY) && right < collider.TileColumns) { right++; } while (collider.GetTile(startX, top - 1) && top > 1) { top--; } while (collider.GetTile(startX, bottom) && bottom < collider.TileRows) { bottom++; } //create the rectangle the tank collides with return(new Rectangle(left * collider.TileWidth, top * collider.TileHeight, (right - left) * collider.TileWidth, (bottom - top) * collider.TileHeight)); }
public void PlaceTile(int x, int y) { // Convert the x and y to a grid position. x = (int)Util.Floor(x / GridSize); y = (int)Util.Floor(y / GridSize); // Place a tile if a tile isn't already there. if (!GridCollider.GetTile(x, y)) { GridCollider.SetTile(x, y, true); needsUpdate = true; } }
/// <summary> /// <para>List of rectangles we collide with.</para> /// <para>This function checks a specified area for collidable tiles to detect the exact position of the obstacle, /// because the gridcollider does not provide such information, and then calls <c>ExtendCollisionTile</c> to detect /// the complete obstacle (as opposed to only the tile we collide with)</para> /// </summary> /// <param name="collider">Collider to use</param> /// <param name="collidingEntity">Entity colliding with the Grid, for example a Tank</param> /// <param name="leftStart">left tile to start check at</param> /// <param name="topStart">top tile to start check at</param> /// <param name="checkWidth">how many tiles to check in x</param> /// <param name="checkHeight">how many tiles to check in y</param> /// <returns>List of rectangles we collide with</returns> public static List <Rectangle> GetCollidingRectangles(GridCollider collider, Entity collidingEntity, int leftStart, int topStart, int checkWidth = 3, int checkHeight = 3) { //create the test entity if it does not exist yet if (_testingEntity == null) { _testingEntity = new Entity(0, 0, null, new BoxCollider(0, 0, CollidableTags.Tester)); } //create list for collisions List <Rectangle> collisionList = new List <Rectangle>(); //check each tile underneath the tank for collision for (int x = leftStart; x < checkWidth + leftStart; x++) { for (int y = topStart; y < checkHeight + topStart; y++) { //if we found a tile that actually collides, save it to the list if (collider.GetTile(x, y)) { _testingEntity.Collider.SetPosition(x * collider.TileWidth, y * collider.TileHeight); _testingEntity.Collider.Width = collider.TileWidth; _testingEntity.Collider.Height = collider.TileHeight; if (collidingEntity.Collider.Collide(collidingEntity.X, collidingEntity.Y, _testingEntity) != null) { collisionList.Add(ExtendCollisionTile(collider, x, y)); } } } } //return return(collisionList); }
/// <summary> /// Load tiles in from a GridCollider. /// </summary> /// <param name="grid">The GridCollider to reference.</param> /// <param name="color">The color to set tiles that are collidable on the grid.</param> /// <param name="layer">The layer to place the tiles on.</param> public void LoadGrid(GridCollider grid, Color color, string layer = "") { for (var i = 0; i < grid.TileColumns; i++) { for (var j = 0; j < grid.TileRows; j++) { if (grid.GetTile(i, j)) { SetTile(i, j, color, layer); } } } }
/// <summary> /// Load tiles in from a GridCollider and choose tiles based on the shape of the grid. /// </summary> /// <param name="grid">The GridCollider to reference.</param> /// <param name="layer">The layer to place the tiles on.</param> public void LoadGridAutoTile(GridCollider grid, string layer = "") { if (autoTileTable == null) { SetAutoTileData(autoTileDefaultData); } for (var i = 0; i < grid.TileColumns; i++) { for (var j = 0; j < grid.TileRows; j++) { if (grid.GetTile(i, j)) { int tileValue = 0; /* * auto tiling grid * * 128 001 016 * 008 ___ 002 * 064 004 032 * */ if (grid.GetTile(i - 1, j - 1)) { tileValue += 128; } if (grid.GetTile(i, j - 1)) { tileValue += 1; } if (grid.GetTile(i + 1, j - 1)) { tileValue += 16; } if (grid.GetTile(i + 1, j)) { tileValue += 2; } if (grid.GetTile(i + 1, j + 1)) { tileValue += 32; } if (grid.GetTile(i, j + 1)) { tileValue += 4; } if (grid.GetTile(i - 1, j + 1)) { tileValue += 64; } if (grid.GetTile(i - 1, j)) { tileValue += 8; } if (autoTileTable.ContainsKey(tileValue)) { tileValue = Rand.ChooseElement <int>(autoTileTable[tileValue]); } SetTile(i, j, tileValue, layer); } } } }