mirror of
https://github.com/jcreek/CosmicClash.git
synced 2026-09-16 09:32:02 +00:00
feat(*): Add 3-2-1 kickoff countdown before play and after goals
This commit is contained in:
@@ -117,16 +117,4 @@ common/physics_interpolation=true
|
|||||||
|
|
||||||
[autoload]
|
[autoload]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
GameSettings="*res://scripts/game_settings.gd"
|
GameSettings="*res://scripts/game_settings.gd"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+22
-1
@@ -1,4 +1,4 @@
|
|||||||
[gd_scene load_steps=6 format=3 uid="uid://c8kak2l3m4n5"]
|
[gd_scene load_steps=7 format=3 uid="uid://c8kak2l3m4n5"]
|
||||||
|
|
||||||
[ext_resource type="Script" uid="uid://du7y176h5aaq4" path="res://scripts/HUDController.gd" id="1_hud_controller"]
|
[ext_resource type="Script" uid="uid://du7y176h5aaq4" path="res://scripts/HUDController.gd" id="1_hud_controller"]
|
||||||
[ext_resource type="Script" path="res://scripts/hud_attitude_indicator.gd" id="2_adi"]
|
[ext_resource type="Script" path="res://scripts/hud_attitude_indicator.gd" id="2_adi"]
|
||||||
@@ -8,6 +8,9 @@
|
|||||||
[sub_resource type="LabelSettings" id="LabelSettings_hud"]
|
[sub_resource type="LabelSettings" id="LabelSettings_hud"]
|
||||||
font_size = 32
|
font_size = 32
|
||||||
|
|
||||||
|
[sub_resource type="LabelSettings" id="LabelSettings_kickoff"]
|
||||||
|
font_size = 96
|
||||||
|
|
||||||
[node name="HUD" type="CanvasLayer"]
|
[node name="HUD" type="CanvasLayer"]
|
||||||
process_mode = 3
|
process_mode = 3
|
||||||
script = ExtResource("1_hud_controller")
|
script = ExtResource("1_hud_controller")
|
||||||
@@ -62,6 +65,24 @@ theme_override_colors/font_color = Color(1, 0.5, 0.15, 1)
|
|||||||
theme_override_font_sizes/font_size = 32
|
theme_override_font_sizes/font_size = 32
|
||||||
text = "0"
|
text = "0"
|
||||||
|
|
||||||
|
[node name="KickoffLabel" type="Label" parent="Control"]
|
||||||
|
visible = false
|
||||||
|
layout_mode = 1
|
||||||
|
anchors_preset = 8
|
||||||
|
anchor_left = 0.5
|
||||||
|
anchor_top = 0.5
|
||||||
|
anchor_right = 0.5
|
||||||
|
anchor_bottom = 0.5
|
||||||
|
offset_left = -90.0
|
||||||
|
offset_top = -60.0
|
||||||
|
offset_right = 90.0
|
||||||
|
offset_bottom = 60.0
|
||||||
|
grow_horizontal = 2
|
||||||
|
grow_vertical = 2
|
||||||
|
label_settings = SubResource("LabelSettings_kickoff")
|
||||||
|
horizontal_alignment = 1
|
||||||
|
vertical_alignment = 1
|
||||||
|
|
||||||
[node name="ResultOverlay" type="Control" parent="Control"]
|
[node name="ResultOverlay" type="Control" parent="Control"]
|
||||||
visible = false
|
visible = false
|
||||||
layout_mode = 1
|
layout_mode = 1
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ class_name HUDController
|
|||||||
@onready var score_row = get_node_or_null("Control/ScoreRow")
|
@onready var score_row = get_node_or_null("Control/ScoreRow")
|
||||||
@onready var team0_score_label = get_node_or_null("Control/ScoreRow/Team0Score")
|
@onready var team0_score_label = get_node_or_null("Control/ScoreRow/Team0Score")
|
||||||
@onready var team1_score_label = get_node_or_null("Control/ScoreRow/Team1Score")
|
@onready var team1_score_label = get_node_or_null("Control/ScoreRow/Team1Score")
|
||||||
|
@onready var kickoff_label = get_node_or_null("Control/KickoffLabel")
|
||||||
@onready var result_overlay = get_node_or_null("Control/ResultOverlay")
|
@onready var result_overlay = get_node_or_null("Control/ResultOverlay")
|
||||||
@onready var result_label = get_node_or_null("Control/ResultOverlay/Center/VBox/ResultLabel")
|
@onready var result_label = get_node_or_null("Control/ResultOverlay/Center/VBox/ResultLabel")
|
||||||
@onready var final_score_label = get_node_or_null("Control/ResultOverlay/Center/VBox/FinalScoreLabel")
|
@onready var final_score_label = get_node_or_null("Control/ResultOverlay/Center/VBox/FinalScoreLabel")
|
||||||
@@ -72,6 +73,9 @@ func _initialize_hud():
|
|||||||
if game_manager and game_manager.has_signal("match_ended"):
|
if game_manager and game_manager.has_signal("match_ended"):
|
||||||
game_manager.match_ended.connect(_on_match_ended)
|
game_manager.match_ended.connect(_on_match_ended)
|
||||||
|
|
||||||
|
if game_manager and game_manager.has_signal("kickoff_countdown"):
|
||||||
|
game_manager.kickoff_countdown.connect(_on_kickoff_countdown)
|
||||||
|
|
||||||
func _connect_ship_signals():
|
func _connect_ship_signals():
|
||||||
# Route ship telemetry to the flight instruments
|
# Route ship telemetry to the flight instruments
|
||||||
if ship.has_signal("speed_changed"):
|
if ship.has_signal("speed_changed"):
|
||||||
@@ -127,6 +131,13 @@ func _on_score_changed(score: Dictionary):
|
|||||||
if team1_score_label and is_instance_valid(team1_score_label):
|
if team1_score_label and is_instance_valid(team1_score_label):
|
||||||
team1_score_label.text = str(score.get(1, 0))
|
team1_score_label.text = str(score.get(1, 0))
|
||||||
|
|
||||||
|
func _on_kickoff_countdown(count: int):
|
||||||
|
if not kickoff_label or not is_instance_valid(kickoff_label):
|
||||||
|
return
|
||||||
|
kickoff_label.visible = count > 0
|
||||||
|
if count > 0:
|
||||||
|
kickoff_label.text = str(count)
|
||||||
|
|
||||||
func _on_match_ended(winning_team: int, score: Dictionary):
|
func _on_match_ended(winning_team: int, score: Dictionary):
|
||||||
if not result_overlay or not is_instance_valid(result_overlay):
|
if not result_overlay or not is_instance_valid(result_overlay):
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -9,9 +9,12 @@ signal timer_updated(minutes: int, seconds: int)
|
|||||||
signal score_changed(score: Dictionary)
|
signal score_changed(score: Dictionary)
|
||||||
# winning_team is -1 for a draw.
|
# winning_team is -1 for a draw.
|
||||||
signal match_ended(winning_team: int, score: Dictionary)
|
signal match_ended(winning_team: int, score: Dictionary)
|
||||||
|
# Counts 3, 2, 1, then 0 ("go", hide the label).
|
||||||
|
signal kickoff_countdown(count: int)
|
||||||
|
|
||||||
# How long the result overlay stays up before returning to the menu.
|
# How long the result overlay stays up before returning to the menu.
|
||||||
const RESULT_SCREEN_SECONDS := 5.0
|
const RESULT_SCREEN_SECONDS := 5.0
|
||||||
|
const KICKOFF_COUNTDOWN_SECONDS := 3
|
||||||
|
|
||||||
@export var match_length_seconds := 150.0
|
@export var match_length_seconds := 150.0
|
||||||
|
|
||||||
@@ -32,6 +35,8 @@ func _start() -> void:
|
|||||||
spawn_camera_rig(player_ship)
|
spawn_camera_rig(player_ship)
|
||||||
spawn_ship(1, 0, _make_opponent_controller())
|
spawn_ship(1, 0, _make_opponent_controller())
|
||||||
|
|
||||||
|
await _run_kickoff_countdown()
|
||||||
|
|
||||||
match_timer = Timer.new()
|
match_timer = Timer.new()
|
||||||
match_timer.one_shot = true
|
match_timer.one_shot = true
|
||||||
match_timer.wait_time = match_length_seconds
|
match_timer.wait_time = match_length_seconds
|
||||||
@@ -66,8 +71,34 @@ func _on_goal_scored(conceding_team: int) -> void:
|
|||||||
score[scoring_team] += 1
|
score[scoring_team] += 1
|
||||||
score_changed.emit(score.duplicate())
|
score_changed.emit(score.duplicate())
|
||||||
print("Goal for team %d! Score: %d - %d" % [scoring_team, score[0], score[1]])
|
print("Goal for team %d! Score: %d - %d" % [scoring_team, score[0], score[1]])
|
||||||
|
await _run_kickoff_countdown()
|
||||||
|
|
||||||
|
|
||||||
|
# Used both for the initial kickoff and after every goal. Freezes ball/ships
|
||||||
|
# via RigidBody3D.freeze — a built-in engine property — so this needs zero
|
||||||
|
# changes to ship.gd/ball.gd/ship_controller.gd, keeping training_mode.gd
|
||||||
|
# (which never calls into this file) completely untouched.
|
||||||
|
func _run_kickoff_countdown() -> void:
|
||||||
reset_ball()
|
reset_ball()
|
||||||
reset_ships()
|
reset_ships()
|
||||||
|
_set_frozen(true)
|
||||||
|
for count in range(KICKOFF_COUNTDOWN_SECONDS, 0, -1):
|
||||||
|
kickoff_countdown.emit(count)
|
||||||
|
# process_always=false: if full-time fires mid-countdown (see
|
||||||
|
# _on_match_timer_timeout's get_tree().paused = true), this stalls
|
||||||
|
# harmlessly in lockstep with the pause instead of ticking a
|
||||||
|
# countdown label over the results screen.
|
||||||
|
await get_tree().create_timer(1.0, false).timeout
|
||||||
|
kickoff_countdown.emit(0)
|
||||||
|
_set_frozen(false)
|
||||||
|
|
||||||
|
|
||||||
|
func _set_frozen(frozen: bool) -> void:
|
||||||
|
if is_instance_valid(ball):
|
||||||
|
ball.set_deferred("freeze", frozen)
|
||||||
|
for ship in ships:
|
||||||
|
if is_instance_valid(ship):
|
||||||
|
ship.set_deferred("freeze", frozen)
|
||||||
|
|
||||||
|
|
||||||
func _on_match_timer_timeout() -> void:
|
func _on_match_timer_timeout() -> void:
|
||||||
|
|||||||
Reference in New Issue
Block a user