diff --git a/_Core/systems/GridSystem.gd b/_Core/systems/GridSystem.gd new file mode 100644 index 0000000..06f44a3 --- /dev/null +++ b/_Core/systems/GridSystem.gd @@ -0,0 +1,143 @@ +# ============================================================================ +# 网格系统 - GridSystem.gd +# +# 提供32x32像素的最小网格单元控制,用于规范地图大小和位置计算 +# +# 使用方式: +# var grid_pos = GridSystem.world_to_grid(world_position) +# var world_pos = GridSystem.grid_to_world(grid_position) +# var snapped_pos = GridSystem.snap_to_grid(position) +# ============================================================================ + +class_name GridSystem +extends RefCounted + +# ============================================================================ +# 常量定义 +# ============================================================================ +const GRID_SIZE: int = 32 # 网格单元大小 32x32 像素 +const HALF_GRID_SIZE: float = GRID_SIZE * 0.5 # 网格中心偏移 + +# ============================================================================ +# 坐标转换方法 +# ============================================================================ + +# 世界坐标转换为网格坐标 +static func world_to_grid(world_pos: Vector2) -> Vector2i: + return Vector2i( + int(world_pos.x / GRID_SIZE), + int(world_pos.y / GRID_SIZE) + ) + +# 网格坐标转换为世界坐标(返回网格左上角) +static func grid_to_world(grid_pos: Vector2i) -> Vector2: + return Vector2( + grid_pos.x * GRID_SIZE, + grid_pos.y * GRID_SIZE + ) + +# 网格坐标转换为世界坐标(返回网格中心) +static func grid_to_world_center(grid_pos: Vector2i) -> Vector2: + return Vector2( + grid_pos.x * GRID_SIZE + HALF_GRID_SIZE, + grid_pos.y * GRID_SIZE + HALF_GRID_SIZE + ) + +# 将位置吸附到最近的网格点(左上角) +static func snap_to_grid(position: Vector2) -> Vector2: + return Vector2( + floor(position.x / GRID_SIZE) * GRID_SIZE, + floor(position.y / GRID_SIZE) * GRID_SIZE + ) + +# 将位置吸附到最近的网格中心 +static func snap_to_grid_center(position: Vector2) -> Vector2: + var grid_pos = world_to_grid(position) + return grid_to_world_center(grid_pos) + +# ============================================================================ +# 距离和区域计算 +# ============================================================================ + +# 计算两个网格坐标之间的曼哈顿距离 +static func grid_distance_manhattan(grid_pos1: Vector2i, grid_pos2: Vector2i) -> int: + return abs(grid_pos1.x - grid_pos2.x) + abs(grid_pos1.y - grid_pos2.y) + +# 计算两个网格坐标之间的欧几里得距离 +static func grid_distance_euclidean(grid_pos1: Vector2i, grid_pos2: Vector2i) -> float: + var diff = grid_pos1 - grid_pos2 + return sqrt(diff.x * diff.x + diff.y * diff.y) + +# 获取指定网格坐标周围的邻居网格(4方向) +static func get_grid_neighbors_4(grid_pos: Vector2i) -> Array[Vector2i]: + return [ + Vector2i(grid_pos.x, grid_pos.y - 1), # 上 + Vector2i(grid_pos.x + 1, grid_pos.y), # 右 + Vector2i(grid_pos.x, grid_pos.y + 1), # 下 + Vector2i(grid_pos.x - 1, grid_pos.y) # 左 + ] + +# 获取指定网格坐标周围的邻居网格(8方向) +static func get_grid_neighbors_8(grid_pos: Vector2i) -> Array[Vector2i]: + var neighbors: Array[Vector2i] = [] + for x in range(-1, 2): + for y in range(-1, 2): + if x == 0 and y == 0: + continue + neighbors.append(Vector2i(grid_pos.x + x, grid_pos.y + y)) + return neighbors + +# ============================================================================ +# 区域和边界检查 +# ============================================================================ + +# 检查网格坐标是否在指定矩形区域内 +static func is_grid_in_bounds(grid_pos: Vector2i, min_grid: Vector2i, max_grid: Vector2i) -> bool: + return (grid_pos.x >= min_grid.x and grid_pos.x <= max_grid.x and + grid_pos.y >= min_grid.y and grid_pos.y <= max_grid.y) + +# 获取矩形区域内的所有网格坐标 +static func get_grids_in_rect(min_grid: Vector2i, max_grid: Vector2i) -> Array[Vector2i]: + var grids: Array[Vector2i] = [] + for x in range(min_grid.x, max_grid.x + 1): + for y in range(min_grid.y, max_grid.y + 1): + grids.append(Vector2i(x, y)) + return grids + +# ============================================================================ +# 地图尺寸规范化 +# ============================================================================ + +# 将像素尺寸规范化为网格尺寸的倍数 +static func normalize_size_to_grid(pixel_size: Vector2i) -> Vector2i: + return Vector2i( + int(ceil(float(pixel_size.x) / GRID_SIZE)) * GRID_SIZE, + int(ceil(float(pixel_size.y) / GRID_SIZE)) * GRID_SIZE + ) + +# 计算指定像素尺寸需要多少个网格单元 +static func get_grid_count(pixel_size: Vector2i) -> Vector2i: + return Vector2i( + int(ceil(float(pixel_size.x) / GRID_SIZE)), + int(ceil(float(pixel_size.y) / GRID_SIZE)) + ) + +# ============================================================================ +# 调试和可视化辅助 +# ============================================================================ + +# 获取网格的边界矩形(用于调试绘制) +static func get_grid_rect(grid_pos: Vector2i) -> Rect2: + var world_pos = grid_to_world(grid_pos) + return Rect2(world_pos, Vector2(GRID_SIZE, GRID_SIZE)) + +# 打印网格信息(调试用) +static func print_grid_info(world_pos: Vector2) -> void: + var grid_pos = world_to_grid(world_pos) + var snapped_pos = snap_to_grid(world_pos) + var center_pos = grid_to_world_center(grid_pos) + + print("世界坐标: ", world_pos) + print("网格坐标: ", grid_pos) + print("吸附位置: ", snapped_pos) + print("网格中心: ", center_pos) \ No newline at end of file diff --git a/_Core/systems/GridSystem.gd.uid b/_Core/systems/GridSystem.gd.uid new file mode 100644 index 0000000..763e586 --- /dev/null +++ b/_Core/systems/GridSystem.gd.uid @@ -0,0 +1 @@ +uid://dceqpffgti4jb