feat: introduce StopNGoManager to handle game phases, mission objectives, and dynamic arena setup with synchronized HUD elements.
This commit is contained in:
@@ -11,7 +11,7 @@ enum Phase {GO, STOP}
|
||||
|
||||
const GO_DURATION: float = 8.0
|
||||
const STOP_DURATION: float = 4.0
|
||||
const REQUIRED_GOALS: int = 5
|
||||
const REQUIRED_GOALS: int = 8
|
||||
|
||||
var current_phase: Phase = Phase.GO
|
||||
var phase_timer: float = GO_DURATION
|
||||
@@ -28,7 +28,6 @@ const TILE_SAFE = 2 # Green Safe Zone
|
||||
const TILE_OBSTACLE = 4 # Wall
|
||||
|
||||
var hud_layer: CanvasLayer
|
||||
var phase_label: Label
|
||||
var mission_label: Label
|
||||
var red_tint_overlay: ColorRect
|
||||
|
||||
@@ -45,6 +44,7 @@ func _ready():
|
||||
|
||||
func _setup_hud():
|
||||
hud_layer = CanvasLayer.new()
|
||||
hud_layer.layer = 5 # Ensure it's above normal UI but below Pause Menu (10)
|
||||
hud_layer.visible = false
|
||||
add_child(hud_layer)
|
||||
|
||||
@@ -55,38 +55,24 @@ func _setup_hud():
|
||||
red_tint_overlay.visible = false # Hidden initially
|
||||
hud_layer.add_child(red_tint_overlay)
|
||||
|
||||
var vbox = VBoxContainer.new()
|
||||
vbox.set_anchors_preset(Control.PRESET_TOP_RIGHT)
|
||||
vbox.offset_right = -20
|
||||
vbox.offset_top = 100
|
||||
hud_layer.add_child(vbox)
|
||||
# New container for bottom-mid label
|
||||
var bottom_container = CenterContainer.new()
|
||||
bottom_container.set_anchors_preset(Control.PRESET_CENTER_BOTTOM)
|
||||
bottom_container.grow_horizontal = Control.GROW_DIRECTION_BOTH
|
||||
bottom_container.grow_vertical = Control.GROW_DIRECTION_BEGIN
|
||||
bottom_container.offset_bottom = -50
|
||||
hud_layer.add_child(bottom_container)
|
||||
|
||||
# Style for HUD
|
||||
var style = StyleBoxFlat.new()
|
||||
style.bg_color = Color(0, 0, 0, 0.4)
|
||||
style.content_margin_left = 10
|
||||
style.content_margin_top = 10
|
||||
style.content_margin_right = 10
|
||||
style.content_margin_bottom = 10
|
||||
|
||||
var panel = PanelContainer.new()
|
||||
panel.add_theme_stylebox_override("panel", style)
|
||||
vbox.add_child(panel)
|
||||
|
||||
var inner_vbox = VBoxContainer.new()
|
||||
panel.add_child(inner_vbox)
|
||||
|
||||
phase_label = Label.new()
|
||||
phase_label.text = "PHASE: GO"
|
||||
phase_label.horizontal_alignment = HORIZONTAL_ALIGNMENT_RIGHT
|
||||
phase_label.add_theme_font_size_override("font_size", 32)
|
||||
phase_label.add_theme_color_override("font_color", Color.GREEN)
|
||||
inner_vbox.add_child(phase_label)
|
||||
var custom_font = load("res://assets/fonts/Nougat-ExtraBlack.ttf")
|
||||
|
||||
mission_label = Label.new()
|
||||
mission_label.text = "MISSION: Collect 3 Items"
|
||||
mission_label.horizontal_alignment = HORIZONTAL_ALIGNMENT_RIGHT
|
||||
inner_vbox.add_child(mission_label)
|
||||
mission_label.text = "MISSION: Collect Goals"
|
||||
mission_label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
|
||||
if custom_font: mission_label.add_theme_font_override("font", custom_font)
|
||||
mission_label.add_theme_font_size_override("font_size", 28) # Slightly larger since it's centered
|
||||
mission_label.add_theme_color_override("font_outline_color", Color.BLACK)
|
||||
mission_label.add_theme_constant_override("outline_size", 8)
|
||||
bottom_container.add_child(mission_label)
|
||||
|
||||
func _process(delta):
|
||||
if not is_active:
|
||||
@@ -105,12 +91,13 @@ func _process(delta):
|
||||
# Update HUD locally
|
||||
_update_hud_visuals()
|
||||
|
||||
func _on_goal_count_updated(_peer_id: int, _count: int):
|
||||
# Refresh visuals whenever points change
|
||||
_update_hud_visuals()
|
||||
|
||||
var _has_notified_mission_complete: bool = false
|
||||
|
||||
func _update_hud_visuals():
|
||||
var phase_name = "GO" if current_phase == Phase.GO else "STOP"
|
||||
if phase_label:
|
||||
phase_label.text = "PHASE: %s (%.0fs)" % [phase_name, max(0, phase_timer)]
|
||||
phase_label.add_theme_color_override("font_color", Color.GREEN if current_phase == Phase.GO else Color.RED)
|
||||
|
||||
# Toggle Red Screen Tint
|
||||
if red_tint_overlay:
|
||||
red_tint_overlay.visible = (current_phase == Phase.STOP)
|
||||
@@ -128,8 +115,16 @@ func _update_hud_visuals():
|
||||
if completed_count >= REQUIRED_GOALS:
|
||||
mission_label.text = "ALL GOALS COMPLETE!\nREACH THE FINISH!"
|
||||
mission_label.add_theme_color_override("font_color", Color.GOLD)
|
||||
|
||||
# Notify player once
|
||||
if my_id == multiplayer.get_unique_id() and not _has_notified_mission_complete:
|
||||
_has_notified_mission_complete = true
|
||||
var player_node = main.get_node_or_null(str(my_id))
|
||||
if player_node:
|
||||
NotificationManager.send_message(player_node, "ALL GOALS COMPLETE!", NotificationManager.MessageType.GOAL)
|
||||
else:
|
||||
mission_label.add_theme_color_override("font_color", Color.WHITE)
|
||||
_has_notified_mission_complete = false
|
||||
|
||||
# Update StopTimer (Traffic Light)
|
||||
_update_stop_timer_visuals()
|
||||
@@ -190,6 +185,14 @@ func activate_client_side():
|
||||
is_active = true
|
||||
if hud_layer:
|
||||
hud_layer.visible = true
|
||||
|
||||
# Connect to GoalsCycleManager for immediate HUD updates
|
||||
var main = get_node_or_null("/root/Main")
|
||||
if main:
|
||||
var gcm = main.get_node_or_null("GoalsCycleManager")
|
||||
if gcm and not gcm.goal_count_updated.is_connected(_on_goal_count_updated):
|
||||
gcm.goal_count_updated.connect(_on_goal_count_updated)
|
||||
|
||||
set_process(true)
|
||||
|
||||
func start_game_mode():
|
||||
|
||||
Reference in New Issue
Block a user