feat: implement core game scene, player logic, and modular manager architecture for Tekton Dash

This commit is contained in:
Yogi Wiguna
2026-03-31 22:08:57 +08:00
parent 1c4d3170ef
commit a88839b396
4 changed files with 38 additions and 61 deletions
+10 -16
View File
@@ -1171,7 +1171,7 @@ func _precalculate_static_positions():
# Calculate 3 spots and STORE them # Calculate 3 spots and STORE them
var points: Array[Vector2i] = [] var points: Array[Vector2i] = []
points = static_tekton_manager.calculate_spawn_points(3, enhanced_gridmap) points = static_tekton_manager.calculate_spawn_points(5, enhanced_gridmap)
reserved_static_positions = points reserved_static_positions = points
print("[Main] Pre-calculated Static Tekton Positions: %s" % str(reserved_static_positions)) print("[Main] Pre-calculated Static Tekton Positions: %s" % str(reserved_static_positions))
@@ -1193,22 +1193,16 @@ func spawn_static_tektons():
# Use pre-calculated points if available # Use pre-calculated points if available
var spawn_points: Array[Vector2i] = [] var spawn_points: Array[Vector2i] = []
if not reserved_static_positions.is_empty(): if not reserved_static_positions.is_empty():
spawn_points = reserved_static_positions # Pick exactly 3 from the 5 reserved potential spots as requested
var possible_points = reserved_static_positions.duplicate()
possible_points.shuffle()
spawn_points = possible_points.slice(0, 3)
else: else:
# If pre-calculation failed, we MUST check for player overlaps now # Fallback if not pre-calculated
var raw_points = static_tekton_manager.calculate_spawn_points(3, enhanced_gridmap) var raw_points = static_tekton_manager.calculate_spawn_points(5, enhanced_gridmap)
var all_players = get_tree().get_nodes_in_group("Players") raw_points.shuffle()
spawn_points = raw_points.slice(0, 3)
for p_spot in raw_points: reserved_static_positions = raw_points # Save all 5 for player avoidance
var is_overlapping = false
for player in all_players:
if abs(p_spot.x - player.current_position.x) <= 2 and abs(p_spot.y - player.current_position.y) <= 2:
is_overlapping = true
break
if not is_overlapping:
spawn_points.append(p_spot)
reserved_static_positions = spawn_points # Save them
print("[Main] Spawning Static Tektons at: %s" % str(spawn_points)) print("[Main] Spawning Static Tektons at: %s" % str(spawn_points))
+1 -8
View File
@@ -1345,20 +1345,13 @@ func is_position_occupied(pos: Vector2i) -> bool:
if p.is_player_moving and p.target_position == pos: if p.is_player_moving and p.target_position == pos:
return true return true
# Prevent overlap with Static Tekton Stands (Exactly the 3x3 area) # Prevent overlap with Static Tekton Stands (Exactly the 3x3 area) using the actual spawned nodes
if enhanced_gridmap:
for stand in get_tree().get_nodes_in_group("StaticTektonStands"): for stand in get_tree().get_nodes_in_group("StaticTektonStands"):
var local_pos = enhanced_gridmap.to_local(stand.global_position) var local_pos = enhanced_gridmap.to_local(stand.global_position)
var stand_map_pos = enhanced_gridmap.local_to_map(local_pos) var stand_map_pos = enhanced_gridmap.local_to_map(local_pos)
if abs(pos.x - stand_map_pos.x) <= 1 and abs(pos.y - stand_map_pos.z) <= 1: if abs(pos.x - stand_map_pos.x) <= 1 and abs(pos.y - stand_map_pos.z) <= 1:
return true return true
var main_node = get_tree().get_root().get_node_or_null("Main")
if main_node and "reserved_static_positions" in main_node:
for reserved in main_node.reserved_static_positions:
if abs(pos.x - reserved.x) <= 1 and abs(pos.y - reserved.y) <= 1:
return true
return false return false
func find_valid_starting_position() -> Vector2i: func find_valid_starting_position() -> Vector2i:
+1 -1
View File
@@ -95,7 +95,7 @@ func simple_move_to(grid_position: Vector2i) -> bool:
if is_wall_passable: if is_wall_passable:
var impenetrable_coords = [ var impenetrable_coords = [
Vector2i(0,0), Vector2i(1,0), Vector2i(2,0), Vector2i(3,0), Vector2i(4,0), Vector2i(5,0), Vector2i(6,0), Vector2i(7,0), Vector2i(8,0), Vector2i(9,0), Vector2i(10,0), Vector2i(13,0), Vector2i(19,0), Vector2i(20,0), Vector2i(21,0), Vector2i(22,0), Vector2i(0,0), Vector2i(1,0), Vector2i(2,0), Vector2i(3,0), Vector2i(4,0), Vector2i(5,0), Vector2i(6,0), Vector2i(7,0), Vector2i(8,0), Vector2i(9,0), Vector2i(10,0), Vector2i(13,0), Vector2i(19,0), Vector2i(20,0), Vector2i(21,0), Vector2i(22,0),
Vector2i(0,1), Vector2i(1,1), Vector2i(2,1), Vector2i(3,1), Vector2i(6,1), Vector2i(0,1), Vector2i(2,1), Vector2i(3,1), Vector2i(6,1),
Vector2i(0,2), Vector2i(1,2), Vector2i(2,2), Vector2i(3,2), Vector2i(0,2), Vector2i(1,2), Vector2i(2,2), Vector2i(3,2),
Vector2i(17,9), Vector2i(18,9), Vector2i(19,9), Vector2i(20,9), Vector2i(21,9), Vector2i(22,9), Vector2i(17,9), Vector2i(18,9), Vector2i(19,9), Vector2i(20,9), Vector2i(21,9), Vector2i(22,9),
Vector2i(11,10), Vector2i(12,10), Vector2i(13,10), Vector2i(15,10), Vector2i(16,10), Vector2i(17,10), Vector2i(18,10), Vector2i(19,10), Vector2i(20,10), Vector2i(21,10), Vector2i(22,10), Vector2i(11,10), Vector2i(12,10), Vector2i(13,10), Vector2i(15,10), Vector2i(16,10), Vector2i(17,10), Vector2i(18,10), Vector2i(19,10), Vector2i(20,10), Vector2i(21,10), Vector2i(22,10),
+24 -34
View File
@@ -13,48 +13,38 @@ const STATIC_CONTROLLER_SCRIPT = "res://scripts/static_tekton_controller.gd"
# Mid-Left, Mid-Mid, Mid-Right # Mid-Left, Mid-Mid, Mid-Right
# Bot-Left, Bot-Mid, Bot-Right # Bot-Left, Bot-Mid, Bot-Right
func calculate_spawn_points(count: int, gridmap: Node) -> Array[Vector2i]: func calculate_spawn_points(_count: int, gridmap: Node) -> Array[Vector2i]:
""" """
Calculates random spawn positions for static tektons. Calculates the 5 fixed potential spawn positions for static tektons.
Returns an Array of Vector2i positions. Corners: (1,1), (W-2,1), (1,H-2), (W-2,H-2)
Center: (W/2, H/2)
Returns exactly 5 spots if possible.
""" """
if count <= 0 or not gridmap: return [] if not gridmap: return []
print("[StaticTektonManager] Calculating static tekton positions (Fixed 5-Zone + Center)...")
# 1. Define Zones (3x3 Grid)
var width = gridmap.columns var width = gridmap.columns
var depth = gridmap.rows var height = gridmap.rows
var zone_w = width / 3
var zone_d = depth / 3
var zones = [] print("[StaticTektonManager] Calculating static tekton positions (Fixed 5-Spots)...")
for z in range(3):
for x in range(3):
zones.append(Rect2i(x * zone_w, z * zone_d, zone_w, zone_d))
# 2. Select Fixed Targets: TL(0), TR(2), Center(4), BL(6), BR(8) # Fixed Spots
# This ensures they are never adjacent (always separated by a middle zone) var spots: Array[Vector2i] = [
var target_indices = [0, 2, 6, 8, 4] Vector2i(1, 1), # Top-Left
target_indices.shuffle() # Randomize which of the 5 zones we pick Vector2i(width - 2, 1), # Top-Right
Vector2i(1, height - 2), # Bottom-Left
Vector2i(width - 2, height - 2), # Bottom-Right
Vector2i(width / 2, height / 2) # Center
]
# If count < 5, we prioritize corners then center # Validate spots (ensure they are walkable and have room)
# If count > 5, we only return 5 because that's the max safe non-adjacent set in 3x3 var valid_spots: Array[Vector2i] = []
var spawn_points: Array[Vector2i] = [] for spot in spots:
if _is_valid_3x3(spot, gridmap):
valid_spots.append(spot)
else:
print("[StaticTektonManager] Warning: Spot %s is not a valid 3x3 walkable area!" % str(spot))
for zone_idx in target_indices: return valid_spots
if spawn_points.size() >= count:
break
var zone = zones[zone_idx]
# Determine Position Type for Bias
# 0:TL, 1:TR, 2:BL, 3:BR, 4:Center
# We pass zone_idx to _pick_spot_in_zone to snap corners
var pos = _pick_spot_in_zone(zone, gridmap, zone_idx)
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: func _pick_spot_in_zone_biased(zone: Rect2i, gridmap: Node, type: int) -> Vector2i:
# type: 0=TL, 1=TR, 2=BL, 3=BR, 4=Center # type: 0=TL, 1=TR, 2=BL, 3=BR, 4=Center