Menu, options with changeable controls, fade transition, placeholder background

This commit is contained in:
2026-07-22 19:45:49 +03:00
parent d379b215e2
commit c283eb0927
13 changed files with 739 additions and 22 deletions
+178 -1
View File
@@ -33,6 +33,7 @@ var _bull_anim: AnimationPlayer = null
var _charge_ready_emitter: CPUParticles3D = null
var _slam_pending: bool = false
var _charge_trail_emitter: CPUParticles3D = null
const MAX_HEALTH: int = 10
var health: int = MAX_HEALTH
@@ -161,6 +162,49 @@ func _setup_charge_indicators() -> void:
_charge_ready_emitter.scale_amount_curve = burst_scale
cube_guy.add_child(_charge_ready_emitter)
# Blue energy trail — streams backward during charge
var trail_mat := StandardMaterial3D.new()
trail_mat.shading_mode = BaseMaterial3D.SHADING_MODE_UNSHADED
trail_mat.transparency = BaseMaterial3D.TRANSPARENCY_ALPHA
trail_mat.vertex_color_use_as_albedo = true
trail_mat.cull_mode = BaseMaterial3D.CULL_DISABLED
var trail_sphere := SphereMesh.new()
trail_sphere.radius = 0.065
trail_sphere.height = 0.13
trail_sphere.radial_segments = 4
trail_sphere.rings = 2
trail_sphere.material = trail_mat
var trail_ramp := Gradient.new()
trail_ramp.set_color(0, Color(0.30, 0.65, 1.0, 1.0))
trail_ramp.set_color(1, Color(0.30, 0.65, 1.0, 0.0))
var trail_scale := Curve.new()
trail_scale.add_point(Vector2(0.0, 1.0))
trail_scale.add_point(Vector2(0.6, 0.8))
trail_scale.add_point(Vector2(1.0, 0.0))
_charge_trail_emitter = CPUParticles3D.new()
_charge_trail_emitter.position = Vector3(0.0, 0.25, 0.3)
_charge_trail_emitter.emitting = false
_charge_trail_emitter.one_shot = false
_charge_trail_emitter.amount = 18
_charge_trail_emitter.lifetime = 0.30
_charge_trail_emitter.randomness = 0.4
_charge_trail_emitter.local_coords = false
_charge_trail_emitter.direction = Vector3(0.0, 0.2, 1.0).normalized()
_charge_trail_emitter.spread = 25.0
_charge_trail_emitter.gravity = Vector3(0.0, 2.0, 0.0)
_charge_trail_emitter.initial_velocity_min = 4.0
_charge_trail_emitter.initial_velocity_max = 9.0
_charge_trail_emitter.scale_amount_min = 0.4
_charge_trail_emitter.scale_amount_max = 1.2
_charge_trail_emitter.mesh = trail_sphere
_charge_trail_emitter.color_ramp = trail_ramp
_charge_trail_emitter.scale_amount_curve = trail_scale
cube_guy.add_child(_charge_trail_emitter)
func _setup_audio() -> void:
if ResourceLoader.exists("res://sounds/bull_huff.ogg"):
@@ -205,6 +249,8 @@ func _set_dust_state(new_state: DustState) -> void:
p.initial_velocity_min = DP.f("charge_vel_min")
p.initial_velocity_max = DP.f("charge_vel_max")
p.emitting = true
if _charge_trail_emitter:
_charge_trail_emitter.emitting = _dust_state == DustState.CHARGE
func _on_dp_changed(_key: String, _val: Variant) -> void:
@@ -296,6 +342,7 @@ func _activate_dash() -> void:
_dash_dir = Vector3(raw.x, 0.0, raw.z).normalized()
velocity.x = _dash_dir.x * DP.f("dash_speed")
velocity.z = _dash_dir.z * DP.f("dash_speed")
_spawn_dash_burst()
_legs.set(&"charge_pitch_target", DP.f("charge_head_pitch"))
if _huff_player:
_huff_player.pitch_scale = randf_range(0.9, 1.1)
@@ -421,6 +468,8 @@ func _spawn_kick_fx(back_dir: Vector3) -> void:
var origin := global_position + back_dir * 0.55 + Vector3(0.0, -0.25, 0.0)
_spawn_kick_dust(origin, back_dir)
_spawn_kick_stones(origin, back_dir)
_spawn_kick_sparks(origin, back_dir)
_spawn_kick_flash(origin)
camera_pivot.call(&"trigger_hit", 0.35)
@@ -520,6 +569,129 @@ func _spawn_kick_stones(origin: Vector3, back_dir: Vector3) -> void:
)
func _spawn_kick_flash(origin: Vector3) -> void:
var mat := StandardMaterial3D.new()
mat.shading_mode = BaseMaterial3D.SHADING_MODE_UNSHADED
mat.transparency = BaseMaterial3D.TRANSPARENCY_ALPHA
mat.albedo_color = Color(1.0, 0.97, 0.40, 0.0)
mat.cull_mode = BaseMaterial3D.CULL_DISABLED
var sphere := SphereMesh.new()
sphere.radius = 1.0
sphere.height = 2.0
sphere.radial_segments = 8
sphere.rings = 4
sphere.material = mat
var mi := MeshInstance3D.new()
mi.mesh = sphere
mi.material_override = mat
mi.scale = Vector3(0.05, 0.05, 0.05)
get_parent().add_child(mi)
mi.global_position = origin
var tween := create_tween()
tween.set_parallel(true)
tween.tween_property(mi, "scale", Vector3(0.7, 0.7, 0.7), 0.13)\
.set_trans(Tween.TRANS_EXPO).set_ease(Tween.EASE_OUT)
var fade := func(a: float) -> void: mat.albedo_color.a = a
tween.tween_method(fade, 0.92, 0.0, 0.14)\
.set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_IN)
tween.tween_callback(mi.queue_free).set_delay(0.16)
func _spawn_dash_burst() -> void:
var mat := StandardMaterial3D.new()
mat.shading_mode = BaseMaterial3D.SHADING_MODE_UNSHADED
mat.transparency = BaseMaterial3D.TRANSPARENCY_ALPHA
mat.vertex_color_use_as_albedo = true
mat.cull_mode = BaseMaterial3D.CULL_DISABLED
var box := BoxMesh.new()
box.size = Vector3(0.045, 0.045, 0.30)
box.material = mat
var ramp := Gradient.new()
ramp.set_color(0, Color(0.50, 0.82, 1.0, 1.0))
ramp.set_color(1, Color(0.50, 0.82, 1.0, 0.0))
var scale_curve := Curve.new()
scale_curve.add_point(Vector2(0.0, 1.0))
scale_curve.add_point(Vector2(1.0, 0.0))
var p := CPUParticles3D.new()
p.one_shot = true
p.explosiveness = 0.92
p.amount = 18
p.lifetime = 0.22
p.randomness = 0.15
p.local_coords = false
p.direction = _dash_dir
p.spread = 15.0
p.gravity = Vector3.ZERO
p.initial_velocity_min = 18.0
p.initial_velocity_max = 35.0
p.scale_amount_min = 0.8
p.scale_amount_max = 2.8
p.mesh = box
p.color_ramp = ramp
p.scale_amount_curve = scale_curve
get_parent().add_child(p)
p.global_position = global_position + Vector3(0.0, 0.2, 0.0)
p.restart()
get_tree().create_timer(0.6).timeout.connect(func() -> void:
if is_instance_valid(p): p.queue_free()
)
func _spawn_kick_sparks(origin: Vector3, back_dir: Vector3) -> void:
var mat := StandardMaterial3D.new()
mat.shading_mode = BaseMaterial3D.SHADING_MODE_UNSHADED
mat.transparency = BaseMaterial3D.TRANSPARENCY_ALPHA
mat.vertex_color_use_as_albedo = true
mat.cull_mode = BaseMaterial3D.CULL_DISABLED
var sphere := SphereMesh.new()
sphere.radius = 0.04
sphere.height = 0.08
sphere.radial_segments = 3
sphere.rings = 1
sphere.material = mat
var ramp := Gradient.new()
ramp.set_color(0, Color(1.0, 0.98, 0.60, 1.0))
ramp.set_color(1, Color(1.0, 1.0, 1.0, 0.0))
var scale_curve := Curve.new()
scale_curve.add_point(Vector2(0.0, 1.0))
scale_curve.add_point(Vector2(0.5, 0.6))
scale_curve.add_point(Vector2(1.0, 0.0))
var p := CPUParticles3D.new()
p.one_shot = true
p.explosiveness = 0.95
p.amount = 22
p.lifetime = 0.28
p.randomness = 0.4
p.local_coords = false
p.direction = (back_dir + Vector3(0.0, 0.5, 0.0)).normalized()
p.spread = 30.0
p.gravity = Vector3(0.0, -14.0, 0.0)
p.initial_velocity_min = 8.0
p.initial_velocity_max = 18.0
p.scale_amount_min = 0.6
p.scale_amount_max = 2.0
p.mesh = sphere
p.color_ramp = ramp
p.scale_amount_curve = scale_curve
get_parent().add_child(p)
p.global_position = origin
p.restart()
get_tree().create_timer(1.0).timeout.connect(func() -> void:
if is_instance_valid(p): p.queue_free()
)
func _make_slam_ring_mesh() -> ArrayMesh:
const INNER_R: float = 0.82
const OUTER_R: float = 1.00
@@ -616,7 +788,6 @@ func _physics_process(delta: float) -> void:
# Right only → thrust NW (forward-left diagonal)
var left_held := Input.is_action_pressed(&"thrust_left")
var right_held := Input.is_action_pressed(&"thrust_right")
camera_pivot.call(&"set_charge_active", left_held and right_held)
if left_held and right_held:
_thrust_left_charge = 0.0
@@ -716,6 +887,12 @@ func _physics_process(delta: float) -> void:
else:
_set_dust_state(DustState.NONE)
# ── Charge trail direction ────────────────────────────────────────────────
if _dust_state == DustState.CHARGE and _charge_trail_emitter:
var vel_flat := Vector3(velocity.x, 0.0, velocity.z)
if vel_flat.length_squared() > 0.1:
_charge_trail_emitter.direction = (-vel_flat.normalized() + Vector3(0.0, 0.25, 0.0)).normalized()
# ── Hoof sounds ───────────────────────────────────────────────────────────