## SpatialGrid — 2D 空间哈希网格 Autoload(GDScript 外壳) ## 热路径由 C# SpatialGridCs 子节点执行(就绪后接管) ## 权威来源:architecture_design.md §4.3 extends Node const CELL_SIZE: int = 64 # 格子大小(像素) const GRID_COLS: int = 128 # 128×128 格 × 64px = 8192×8192 覆盖范围 const GRID_ROWS: int = 128 const GRID_OFFSET: int = 4096 # 将世界中心映射到网格中心(支持负坐标) var _cs_node: Node = null # SpatialGridCs C# 子节点(就绪后挂载) ## GDScript 回退网格 var _grid: Array = [] # Array[Array[int]] var _entity_cell: Dictionary = {} # { entity_id → cell_idx } func _ready() -> void: _grid.resize(GRID_COLS * GRID_ROWS) for i in _grid.size(): _grid[i] = [] ## 插入或更新实体位置(由 EnemyManager 每物理帧调用) func insert(entity_id: int, pos: Vector2) -> void: if _cs_node and _cs_node.has_method("Insert"): _cs_node.call("Insert", entity_id, pos) return var cx: int = clamp(int((pos.x + GRID_OFFSET) / CELL_SIZE), 0, GRID_COLS - 1) var cy: int = clamp(int((pos.y + GRID_OFFSET) / CELL_SIZE), 0, GRID_ROWS - 1) var cell: int = cx + cy * GRID_COLS var old_cell: int = _entity_cell.get(entity_id, -1) if old_cell == cell: return if old_cell >= 0: _grid[old_cell].erase(entity_id) _grid[cell].append(entity_id) _entity_cell[entity_id] = cell ## 查询圆形范围内的所有实体 ID func query_circle(center: Vector2, radius: float) -> PackedInt32Array: if _cs_node and _cs_node.has_method("QueryCircle"): return _cs_node.call("QueryCircle", center, radius) var result := PackedInt32Array() var min_cx: int = clamp(int((center.x - radius + GRID_OFFSET) / CELL_SIZE), 0, GRID_COLS - 1) var max_cx: int = clamp(int((center.x + radius + GRID_OFFSET) / CELL_SIZE), 0, GRID_COLS - 1) var min_cy: int = clamp(int((center.y - radius + GRID_OFFSET) / CELL_SIZE), 0, GRID_ROWS - 1) var max_cy: int = clamp(int((center.y + radius + GRID_OFFSET) / CELL_SIZE), 0, GRID_ROWS - 1) for cy in range(min_cy, max_cy + 1): for cx in range(min_cx, max_cx + 1): for eid in _grid[cx + cy * GRID_COLS]: result.append(eid) return result ## 每帧由 EnemyManager._physics_process 驱动(dirty-list 方案) func rebuild() -> void: if _cs_node and _cs_node.has_method("Rebuild"): _cs_node.call("Rebuild") ## 移除实体 func remove_entity(entity_id: int) -> void: if _cs_node and _cs_node.has_method("Remove"): _cs_node.call("Remove", entity_id) return var old_cell: int = _entity_cell.get(entity_id, -1) if old_cell >= 0: _grid[old_cell].erase(entity_id) _entity_cell.erase(entity_id) ## 清空(关卡重置) func clear() -> void: if _cs_node and _cs_node.has_method("Clear"): _cs_node.call("Clear") return for cell_list in _grid: (cell_list as Array).clear() _entity_cell.clear()