Files
spellforge/scripts/autoloads/spatial_grid.gd
T
2026-07-20 10:56:52 +08:00

76 lines
2.8 KiB
GDScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
## SpatialGrid — 2D 空间哈希网格 AutoloadGDScript 外壳)
## 热路径由 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()