Menu, options with changeable controls, fade transition, placeholder background
This commit is contained in:
@@ -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 ───────────────────────────────────────────────────────────
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user