feat: Add EnhancedGridMap for dynamic grid generation, pathfinding, and network synchronization, and introduce core game scripts for Tekton entities and managers.
This commit is contained in:
@@ -20,38 +20,109 @@ func calculate_spawn_points(count: int, gridmap: Node) -> Array:
|
||||
"""
|
||||
if count <= 0 or not gridmap: return []
|
||||
|
||||
print("[StaticTektonManager] Calculating %d static tekton positions..." % count)
|
||||
print("[StaticTektonManager] Calculating static tekton positions (Fixed 5-Zone + Center)...")
|
||||
|
||||
# 1. Define Zones
|
||||
# 1. Define Zones (3x3 Grid)
|
||||
var width = gridmap.columns
|
||||
var depth = gridmap.rows
|
||||
|
||||
# Simple 3x3 grid partition
|
||||
var zone_w = width / 3
|
||||
var zone_d = depth / 3
|
||||
|
||||
var all_zones = []
|
||||
var zones = []
|
||||
for z in range(3):
|
||||
for x in range(3):
|
||||
# Create Rect2i for each zone (x, y, w, h)
|
||||
var zone_rect = Rect2i(x * zone_w, z * zone_d, zone_w, zone_d)
|
||||
all_zones.append(zone_rect)
|
||||
zones.append(Rect2i(x * zone_w, z * zone_d, zone_w, zone_d))
|
||||
|
||||
# 2. Select Zones (Random Distinct)
|
||||
all_zones.shuffle()
|
||||
var selected_zones = all_zones.slice(0, count)
|
||||
# 2. Select Fixed Targets: TL(0), TR(2), Center(4), BL(6), BR(8)
|
||||
# This ensures they are never adjacent (always separated by a middle zone)
|
||||
var target_indices = [0, 2, 6, 8, 4]
|
||||
|
||||
# If count < 5, we prioritize corners then center
|
||||
# If count > 5, we only return 5 because that's the max safe non-adjacent set in 3x3
|
||||
var spawn_points = []
|
||||
|
||||
# 3. Pick Point in each Selected Zone
|
||||
for i in range(selected_zones.size()):
|
||||
var zone = selected_zones[i]
|
||||
var pos = _pick_spot_in_zone(zone, gridmap)
|
||||
var iterations = min(count, target_indices.size())
|
||||
for i in range(iterations):
|
||||
var zone_idx = target_indices[i]
|
||||
var zone = zones[zone_idx]
|
||||
|
||||
# Determine Position Type for Bias
|
||||
# 0:TL, 1:TR, 2:BL, 3:BR, 4:Center
|
||||
var pos_type = -1
|
||||
match zone_idx:
|
||||
0: pos_type = 0 # TL
|
||||
2: pos_type = 1 # TR
|
||||
6: pos_type = 2 # BL
|
||||
8: pos_type = 3 # BR
|
||||
4: pos_type = 4 # Center
|
||||
|
||||
var pos = _pick_spot_in_zone_biased(zone, gridmap, pos_type)
|
||||
if pos != Vector2i(-1, -1):
|
||||
spawn_points.append(pos)
|
||||
|
||||
return spawn_points
|
||||
|
||||
func _pick_spot_in_zone_biased(zone: Rect2i, gridmap: Node, type: int) -> Vector2i:
|
||||
# type: 0=TL, 1=TR, 2=BL, 3=BR, 4=Center
|
||||
|
||||
# ideal target relative to map
|
||||
var target = Vector2i.ZERO
|
||||
match type:
|
||||
0: target = Vector2i(0, 0)
|
||||
1: target = Vector2i(gridmap.columns, 0)
|
||||
2: target = Vector2i(0, gridmap.rows)
|
||||
3: target = Vector2i(gridmap.columns, gridmap.rows)
|
||||
4: target = Vector2i(gridmap.columns / 2, gridmap.rows / 2)
|
||||
|
||||
# Clamp target to be inside valid area (taking 3x3 margin into account)
|
||||
# Center of 3x3 must be at least 1 tile from edge
|
||||
var min_x = max(1, zone.position.x + 1)
|
||||
var max_x = min(gridmap.columns - 2, zone.position.x + zone.size.x - 2)
|
||||
var min_y = max(1, zone.position.y + 1)
|
||||
var max_y = min(gridmap.rows - 2, zone.position.y + zone.size.y - 2)
|
||||
|
||||
if min_x > max_x or min_y > max_y:
|
||||
return Vector2i(-1, -1)
|
||||
|
||||
var clamped_target = Vector2i(
|
||||
clamp(target.x, min_x, max_x),
|
||||
clamp(target.y, min_y, max_y)
|
||||
)
|
||||
|
||||
# BFS to find nearest valid 3x3 spot to clamped_target
|
||||
var queue = [clamped_target]
|
||||
var visited = {clamped_target: true}
|
||||
|
||||
# Limit search to avoid hanging
|
||||
var checks = 0
|
||||
while not queue.is_empty() and checks < 200:
|
||||
var current = queue.pop_front()
|
||||
checks += 1
|
||||
|
||||
if _is_valid_3x3(current, gridmap):
|
||||
return current
|
||||
|
||||
var neighbors = [
|
||||
Vector2i(0, 1), Vector2i(0, -1), Vector2i(1, 0), Vector2i(-1, 0)
|
||||
]
|
||||
|
||||
for n in neighbors:
|
||||
var next = current + n
|
||||
if next.x >= min_x and next.x <= max_x and next.y >= min_y and next.y <= max_y:
|
||||
if not visited.has(next):
|
||||
visited[next] = true
|
||||
queue.append(next)
|
||||
|
||||
return Vector2i(-1, -1)
|
||||
|
||||
func _is_valid_3x3(center: Vector2i, gridmap: Node) -> bool:
|
||||
for dx in range(-1, 2):
|
||||
for dy in range(-1, 2):
|
||||
var check_pos = Vector3i(center.x + dx, 0, center.y + dy)
|
||||
if gridmap.get_cell_item(check_pos) == -1:
|
||||
return false
|
||||
return true
|
||||
|
||||
func _pick_spot_in_zone(zone: Rect2i, gridmap: Node) -> Vector2i:
|
||||
# Find a valid 3x3 spot in the zone
|
||||
# The returned position is the CENTER of the 3x3 area
|
||||
|
||||
Reference in New Issue
Block a user