feat(title): warm shader background, pulsing glow, drifting embers
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -3,7 +3,9 @@ extends Control
|
||||
## The entry-point screen (mock Title Screen). Editor-first (ADR 0001): the whole
|
||||
## composition lives in TitleScreen.tscn; this script drives selection, input, and
|
||||
## dispatches the menu. §2: presentation/state — no AI here (the DM enters at the
|
||||
## shell). The atmosphere (bg shader, glow, embers) is layered on in a later task.
|
||||
## shell). The atmosphere (warm bg shader, pulsing glow, drifting embers) is
|
||||
## configured in code from Palette (the DarkBay precedent) — see _apply_background,
|
||||
## _configure_embers, _pulse_glow.
|
||||
|
||||
signal menu_activated(id: StringName)
|
||||
|
||||
@@ -15,6 +17,8 @@ var _sel: int = 0
|
||||
@onready var _menu: VBoxContainer = $Content/Menu
|
||||
@onready var _footer_left: Label = $FooterLeft
|
||||
@onready var _background: ColorRect = $Background
|
||||
@onready var _glow: ColorRect = $Glow
|
||||
@onready var _embers: GPUParticles2D = $Embers
|
||||
@onready var _rule: ColorRect = $Content/Rule
|
||||
|
||||
|
||||
@@ -25,6 +29,10 @@ func _ready() -> void:
|
||||
|
||||
_background.color = Palette.STAGE_1
|
||||
_rule.color = Palette.GOLD
|
||||
_glow.color = Palette.BLOOD
|
||||
_apply_background()
|
||||
_configure_embers()
|
||||
_pulse_glow()
|
||||
|
||||
_rows = []
|
||||
for row in _menu.get_children():
|
||||
@@ -42,6 +50,48 @@ func _fit_to_viewport() -> void:
|
||||
size = get_viewport_rect().size
|
||||
|
||||
|
||||
func _apply_background() -> void:
|
||||
# Palette-driven shader material set in code (the DarkBay precedent) so no hex
|
||||
# lives in the shader/scene; the editor shows the ColorRect fallback.
|
||||
var mat := ShaderMaterial.new()
|
||||
mat.shader = load("res://assets/theme/shaders/title_background.gdshader")
|
||||
mat.set_shader_parameter("warm", Palette.TITLE_WARM)
|
||||
mat.set_shader_parameter("mid", Palette.TITLE_MID)
|
||||
mat.set_shader_parameter("edge", Palette.STAGE_1)
|
||||
_background.material = mat
|
||||
|
||||
|
||||
func _configure_embers() -> void:
|
||||
var pm := ParticleProcessMaterial.new()
|
||||
pm.emission_shape = ParticleProcessMaterial.EMISSION_SHAPE_BOX
|
||||
pm.emission_box_extents = Vector3(760, 4, 0) # a wide strip along the bottom
|
||||
pm.direction = Vector3(0, -1, 0)
|
||||
pm.spread = 12.0
|
||||
pm.gravity = Vector3(0, -18, 0)
|
||||
pm.initial_velocity_min = 24.0
|
||||
pm.initial_velocity_max = 52.0
|
||||
pm.scale_min = 0.4
|
||||
pm.scale_max = 1.0
|
||||
pm.color = Palette.GOLD_BRIGHT
|
||||
# fade out over life
|
||||
var ramp := Gradient.new()
|
||||
ramp.set_color(0, Color(Palette.GOLD_BRIGHT, 0.0))
|
||||
ramp.set_color(1, Color(Palette.GOLD_BRIGHT, 0.0))
|
||||
ramp.add_point(0.15, Palette.GOLD_BRIGHT)
|
||||
var tex := GradientTexture1D.new()
|
||||
tex.gradient = ramp
|
||||
pm.color_ramp = tex
|
||||
_embers.process_material = pm
|
||||
|
||||
|
||||
func _pulse_glow() -> void:
|
||||
# A slow warm pulse (the off-screen fire). A code tween, not an AnimationPlayer:
|
||||
# a 2-keyframe modulate loop is trivial in code and motion is runtime-only anyway.
|
||||
var tween := create_tween().set_loops().set_trans(Tween.TRANS_SINE)
|
||||
tween.tween_property(_glow, "modulate:a", 0.8, 3.0)
|
||||
tween.tween_property(_glow, "modulate:a", 0.5, 3.0)
|
||||
|
||||
|
||||
func _wire_row_mouse() -> void:
|
||||
for i in range(_rows.size()):
|
||||
var idx := i # fresh per-iteration binding for the closures
|
||||
|
||||
Reference in New Issue
Block a user