extends Resource class_name Grid # The grid size. @export var size := Vector2(100, 100) # The of a cell in pixels @export var cellSize := Vector2(16, 16) @export var cameraPosition := Vector2.ZERO func setCameraPosition(pos: Vector2): cameraPosition = pos @export var cameraZoom := Vector2(2, 2) func setCameraZoom(zoom: Vector2): cameraZoom = zoom @export var screenCenter := Vector2.ZERO func setScreenCenter(pos: Vector2): screenCenter = pos # Half of ``cell_size``. # We will use this to calculate the center of a grid cell in pixels, on the screen. # That's how we can place units in the center of a cell. var _halfCellSize: Vector2 = cellSize / 2 # Returns the position of a cell's center in pixels. # We'll place units and have them move through cells using this function. # Example: # cellSize = (32) # gridPosition = (2, 3) # cameraZoom = 1 # (2,3) * 32 + 16 # (64, 96) + 16 # == (80, 112) <- This is the position ON THE SCREEN. func calculateMapPosition(gridPosition: Vector2) -> Vector2: return (gridPosition * cellSize + _halfCellSize) / cameraZoom # Returns the coordinates of the cell on the grid given a position on the map. # This is the complementary of `calculate_map_position()` above. # When designing a level, you'll place units visually in the editor. We'll use this function to find # the grid coordinates they're placed on, and call `calculate_map_position()` to snap them to the # cell's center. # This is the position IN THE GRID func calculateGridCoordinates(mapPosition: Vector2) -> Vector2: return (mapPosition / cellSize).floor() # Returns true if the `cell_coordinates` are within the grid. # This method and the following one allow us to ensure the cursor or units can never go past the # map's limit. func isWithinBounds(cellCoordinates: Vector2) -> bool: var out := cellCoordinates.x >= 0 and cellCoordinates.x < size.x return out and cellCoordinates.y >= 0 and cellCoordinates.y < size.y # Makes the `grid_position` fit within the grid's bounds. # This is a clamp function designed specifically for our grid coordinates. # The Vector2 class comes with its `Vector2.clamp()` method, but it doesn't work the same way: it # limits the vector's length instead of clamping each of the vector's components individually. # That's why we need to code a new method. func clamp(gridPosition: Vector2) -> Vector2: var out := gridPosition out.x = clamp(out.x, 0, size.x - 1.0) out.y = clamp(out.y, 0, size.y - 1.0) return out # Given Vector2 coordinates, calculates and returns the corresponding integer index. You can use # this function to convert 2D coordinates to a 1D array's indices. # # There are two cases where you need to convert coordinates like so: # 1. We'll need it for the AStar algorithm, which requires a unique index for each point on the # graph it uses to find a path. # 2. You can use it for performance. More on that below. func asIndex(cell: Vector2) -> int: return int(cell.x + size.x * cell.y)