forked from moyin/whale-town-front
143 lines
5.4 KiB
GDScript
143 lines
5.4 KiB
GDScript
# ============================================================================
|
||
# 网格系统 - 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) |