feat: Implement Stop n Go game mode with phase management, missions, dynamic safe zones, and associated UI and managers.

This commit is contained in:
Yogi Wiguna
2026-03-06 16:01:12 +08:00
parent edd5051106
commit 0fb1397d11
8 changed files with 106 additions and 71 deletions
+32 -32
View File
@@ -22,6 +22,16 @@ var safe_zone_spawned: bool = false
# Power-Up Tile Spawning
const POWERUP_TILES = [11, 14] # Speed (11) and Ghost (14)
const POWERUP_SPAWN_COUNT: int = 5 # Number of power-up tiles to spawn
var powerups_spawned: bool = false
var stop_phase_occurred: bool = false
const PERMANENT_POWERUP_LOCATIONS: Array[Vector2i] = [
Vector2i(4, 3), # Area 1
Vector2i(8, 7), # Area 2
Vector2i(11, 4), # Area 3
Vector2i(15, 8), # Area 4
Vector2i(18, 5) # Area 5
]
var current_phase: Phase = Phase.GO
var phase_timer: float = GO_DURATION
@@ -231,6 +241,7 @@ func _start_phase(phase: Phase):
rpc("sync_phase", phase_name, phase_timer)
if phase == Phase.STOP:
stop_phase_occurred = true
# --- DYNAMIC SAFE ZONE: Penalize players outside the zone ---
if safe_zone_spawned:
var all_players = get_tree().get_nodes_in_group("Players")
@@ -238,7 +249,7 @@ func _start_phase(phase: Phase):
if not _is_in_safe_zone(p.current_position):
_scatter_player_tiles(p)
# --- POWER-UP TILES: Spawn 5 Speed & Ghost tiles ---
# Refresh power-ups every STOP phase
_spawn_powerup_tiles()
# If GO phase starts, clear all STOP phase freezes and safe zone
@@ -323,6 +334,11 @@ func setup_mission_tiles():
if multiplayer.is_server():
_spawn_mission_tiles()
func spawn_initial_powerups():
"""Public wrapper to spawn powerups before game start."""
if multiplayer.is_server():
_spawn_powerup_tiles()
func _spawn_mission_tiles():
var gridmap = get_parent().get_node_or_null("EnhancedGridMap")
if not gridmap:
@@ -679,7 +695,7 @@ func sync_clear_safe_zone(centers_to_clear: Array):
# =============================================================================
func _spawn_powerup_tiles():
"""Server: Spawn 5 Speed & Ghost power-up tiles at random walkable positions."""
"""Server: Spawn 5 permanent power-up tiles at fixed positions."""
if not multiplayer.is_server(): return
var main = get_node_or_null("/root/Main")
@@ -688,40 +704,24 @@ func _spawn_powerup_tiles():
var gridmap = main.get_node_or_null("EnhancedGridMap")
if not gridmap: return
# Collect valid positions (walkable floor, no existing item on Floor 1)
var valid_positions: Array[Vector2i] = []
for x in range(gridmap.columns):
for z in range(gridmap.rows):
var floor_tile = gridmap.get_cell_item(Vector3i(x, 0, z))
# Skip void, obstacles, start, finish
if floor_tile == -1 or floor_tile == TILE_OBSTACLE:
continue
# Skip cells that already have items on Floor 1
var existing_item = gridmap.get_cell_item(Vector3i(x, 1, z))
if existing_item != -1:
continue
valid_positions.append(Vector2i(x, z))
print("[StopNGo] Spawning/Refreshing 5 static power-up tiles...")
if valid_positions.is_empty():
print("[StopNGo] WARNING: No valid positions for power-up tiles!")
return
# Shuffle and pick up to POWERUP_SPAWN_COUNT positions
var rng = RandomNumberGenerator.new()
rng.randomize()
valid_positions.shuffle()
var spawn_count = min(POWERUP_SPAWN_COUNT, valid_positions.size())
for i in range(spawn_count):
var pos = valid_positions[i]
var tile_id = POWERUP_TILES[rng.randi() % POWERUP_TILES.size()]
for i in range(PERMANENT_POWERUP_LOCATIONS.size()):
var pos = PERMANENT_POWERUP_LOCATIONS[i]
# Set Floor 0 beneath power-up to ID 1 (Hover pattern) - Static PADS
gridmap.set_cell_item(Vector3i(pos.x, 0, pos.y), 1)
# Cycle through the available power-up types
var tile_id = POWERUP_TILES[i % POWERUP_TILES.size()]
# Place on Floor 1
gridmap.set_cell_item(Vector3i(pos.x, 1, pos.y), tile_id)
# Sync to all clients
# Sync both floor and tile to all clients and host
if can_rpc():
main.rpc("sync_grid_item", pos.x, 1, pos.y, tile_id)
main.rpc("sync_grid_item", pos.x, 0, pos.y, 1) # Sync floor change (Pad on)
main.rpc("sync_grid_item", pos.x, 1, pos.y, tile_id) # Sync power-up
print("[StopNGo] Spawned %d power-up tiles (Speed & Ghost)" % spawn_count)
powerups_spawned = true
print("[StopNGo] Static power-up refresh completed.")