[agent:claude-cli] feat(boost): turbo boost avec énergie/cooldown, barre HUD dynamique, speed lines overlay et son distinct au déclenchement
This commit is contained in:
@@ -31,6 +31,16 @@ var _toasts: Array = [] # each: {"node": PanelContainer, "timer": float}
|
||||
var _biome_cache_pos: Vector3 = Vector3(99999, 99999, 99999)
|
||||
var _biome_cached_name: String = ""
|
||||
|
||||
# Boost bar
|
||||
var _boost_panel: PanelContainer = null
|
||||
var _boost_bar: ProgressBar = null
|
||||
var _boost_label: Label = null
|
||||
|
||||
# Speed lines overlay
|
||||
var _speed_lines: Control = null
|
||||
var _speed_line_data: Array = []
|
||||
const SPEED_LINE_COUNT: int = 16
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
_style_bar(_oxygen_bar, Color(0.31, 0.76, 0.97))
|
||||
@@ -54,6 +64,8 @@ func _ready() -> void:
|
||||
_build_toast_container()
|
||||
_build_consumable_hint()
|
||||
_build_combo_panel()
|
||||
_build_boost_bar()
|
||||
_build_speed_lines()
|
||||
var am: Node = get_node_or_null("/root/AchievementManager")
|
||||
if am != null:
|
||||
am.achievement_unlocked.connect(_on_achievement_unlocked)
|
||||
@@ -513,8 +525,88 @@ func _style_bar(bar: ProgressBar, color: Color) -> void:
|
||||
bar.add_theme_stylebox_override("background", bg_style)
|
||||
|
||||
|
||||
func _build_boost_bar() -> void:
|
||||
_boost_panel = PanelContainer.new()
|
||||
_boost_panel.anchor_left = 0.0
|
||||
_boost_panel.anchor_right = 0.0
|
||||
_boost_panel.anchor_top = 1.0
|
||||
_boost_panel.anchor_bottom = 1.0
|
||||
_boost_panel.offset_left = 16.0
|
||||
_boost_panel.offset_right = 220.0
|
||||
_boost_panel.offset_top = -78.0
|
||||
_boost_panel.offset_bottom = -48.0
|
||||
|
||||
var style := StyleBoxFlat.new()
|
||||
style.bg_color = Color(0.04, 0.06, 0.12, 0.78)
|
||||
style.border_color = Color(0.3, 0.7, 1.0, 0.6)
|
||||
style.set_border_width_all(1)
|
||||
style.set_corner_radius_all(6)
|
||||
_boost_panel.add_theme_stylebox_override("panel", style)
|
||||
|
||||
var vbox := VBoxContainer.new()
|
||||
vbox.add_theme_constant_override("separation", 2)
|
||||
_boost_panel.add_child(vbox)
|
||||
|
||||
_boost_label = Label.new()
|
||||
_boost_label.text = "BOOST"
|
||||
_boost_label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
|
||||
_boost_label.add_theme_font_size_override("font_size", 10)
|
||||
_boost_label.add_theme_color_override("font_color", Color(0.55, 0.85, 1.0))
|
||||
vbox.add_child(_boost_label)
|
||||
|
||||
_boost_bar = ProgressBar.new()
|
||||
_boost_bar.custom_minimum_size = Vector2(188, 7)
|
||||
_boost_bar.max_value = 100.0
|
||||
_boost_bar.value = 100.0
|
||||
_boost_bar.show_percentage = false
|
||||
var fill := StyleBoxFlat.new()
|
||||
fill.bg_color = Color(0.3, 0.75, 1.0)
|
||||
fill.set_corner_radius_all(3)
|
||||
_boost_bar.add_theme_stylebox_override("fill", fill)
|
||||
var bg := StyleBoxFlat.new()
|
||||
bg.bg_color = Color(0.06, 0.08, 0.14, 0.8)
|
||||
bg.set_corner_radius_all(3)
|
||||
_boost_bar.add_theme_stylebox_override("background", bg)
|
||||
vbox.add_child(_boost_bar)
|
||||
|
||||
add_child(_boost_panel)
|
||||
|
||||
|
||||
func _build_speed_lines() -> void:
|
||||
_speed_lines = Control.new()
|
||||
_speed_lines.set_anchors_preset(Control.PRESET_FULL_RECT)
|
||||
_speed_lines.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
||||
_speed_lines.modulate.a = 0.0
|
||||
_speed_lines.draw.connect(_draw_speed_lines)
|
||||
add_child(_speed_lines)
|
||||
# Init line data (angle, length ratio, alpha)
|
||||
for i: int in range(SPEED_LINE_COUNT):
|
||||
_speed_line_data.append({
|
||||
"angle": (float(i) / float(SPEED_LINE_COUNT)) * TAU + randf() * 0.3,
|
||||
"len": randf_range(0.25, 0.75),
|
||||
"alpha": randf_range(0.4, 1.0),
|
||||
"offset": randf_range(0.3, 0.85)
|
||||
})
|
||||
|
||||
|
||||
func _draw_speed_lines() -> void:
|
||||
if _speed_lines == null:
|
||||
return
|
||||
var size: Vector2 = _speed_lines.size
|
||||
var center: Vector2 = size * 0.5
|
||||
var max_r: float = size.length() * 0.55
|
||||
for line: Dictionary in _speed_line_data:
|
||||
var dir: Vector2 = Vector2(cos(line["angle"]), sin(line["angle"]))
|
||||
var start: Vector2 = center + dir * max_r * line["offset"]
|
||||
var end: Vector2 = center + dir * max_r * (line["offset"] + line["len"] * 0.35)
|
||||
var col: Color = Color(0.55, 0.85, 1.0, line["alpha"] * 0.55)
|
||||
_speed_lines.draw_line(start, end, col, 1.5)
|
||||
|
||||
|
||||
func connect_to_dolphin(dolphin: CharacterBody3D) -> void:
|
||||
dolphin.stats_changed.connect(_on_stats_changed)
|
||||
if dolphin.has_signal("boost_changed"):
|
||||
dolphin.boost_changed.connect(_on_boost_changed)
|
||||
_dolphin = dolphin
|
||||
|
||||
var main: Node = get_tree().get_first_node_in_group("main")
|
||||
@@ -546,6 +638,7 @@ func _process(delta: float) -> void:
|
||||
_update_toasts(delta)
|
||||
_update_consumable_hint()
|
||||
_update_combo_bar()
|
||||
_update_speed_lines(delta)
|
||||
|
||||
if not is_instance_valid(_dolphin):
|
||||
return
|
||||
@@ -594,3 +687,46 @@ func _update_biome_label() -> void:
|
||||
_biome_cache_pos = pos
|
||||
_biome_cached_name = WorldGenerator.biome_name_at(pos.x, pos.z, pos.y, _world_seed)
|
||||
_biome_label.text = "Biome : %s" % _biome_cached_name
|
||||
|
||||
|
||||
func _on_boost_changed(energy: float, max_energy: float, active: bool) -> void:
|
||||
if _boost_bar == null:
|
||||
return
|
||||
_boost_bar.max_value = max_energy
|
||||
_boost_bar.value = energy
|
||||
# Color shift: full = cyan, low = orange
|
||||
var t: float = energy / max_energy
|
||||
var fill := StyleBoxFlat.new()
|
||||
fill.bg_color = Color(1.0 - t * 0.7, 0.55 + t * 0.3, t)
|
||||
fill.set_corner_radius_all(3)
|
||||
_boost_bar.add_theme_stylebox_override("fill", fill)
|
||||
if _boost_label != null:
|
||||
_boost_label.text = "BOOST %d%%" % int(energy / max_energy * 100.0)
|
||||
if active:
|
||||
_boost_label.add_theme_color_override("font_color", Color(0.3, 0.9, 1.0))
|
||||
elif energy < max_energy * 0.25:
|
||||
_boost_label.add_theme_color_override("font_color", Color(1.0, 0.45, 0.2))
|
||||
else:
|
||||
_boost_label.add_theme_color_override("font_color", Color(0.55, 0.85, 1.0))
|
||||
|
||||
|
||||
var _boost_active: bool = false
|
||||
|
||||
|
||||
func _update_speed_lines(delta: float) -> void:
|
||||
if _speed_lines == null:
|
||||
return
|
||||
var target_alpha: float = 0.0
|
||||
if is_instance_valid(_dolphin) and _dolphin.get("is_boosting"):
|
||||
if _dolphin.is_boosting:
|
||||
target_alpha = 1.0
|
||||
_boost_active = true
|
||||
# Animate line angles for motion feel
|
||||
var t: float = Time.get_ticks_msec() * 0.001
|
||||
for i: int in range(_speed_line_data.size()):
|
||||
_speed_line_data[i]["angle"] += delta * (0.4 + float(i) * 0.05)
|
||||
else:
|
||||
_boost_active = false
|
||||
_speed_lines.modulate.a = lerpf(_speed_lines.modulate.a, target_alpha, delta * 5.0)
|
||||
if _speed_lines.modulate.a > 0.02:
|
||||
_speed_lines.queue_redraw()
|
||||
|
||||
Reference in New Issue
Block a user