From b30fb6e0a654e07aa093bc7f01bb128fb9d75c0e Mon Sep 17 00:00:00 2001 From: Richard Aasa Date: Mon, 25 May 2026 20:38:38 +0300 Subject: [PATCH] hold right+left, it charges ahead --- bull_legs.gd | 6 +++++- debug_params.gd | 5 +++++ player.gd | 48 +++++++++++++++++++++++++++++++++++++----------- 3 files changed, 47 insertions(+), 12 deletions(-) diff --git a/bull_legs.gd b/bull_legs.gd index e3d0b14..547ab66 100644 --- a/bull_legs.gd +++ b/bull_legs.gd @@ -12,6 +12,9 @@ var _tilt_x: float = 0.0 var _tilt_z: float = 0.0 var _aerial_pitch: float = 0.0 +var charge_pitch_target: float = 0.0 +var _charge_pitch_curr: float = 0.0 + # Tail — Verlet chain simulation const TAIL_BONES: Array = [ &"tail_1", &"tail_2", &"tail_3", &"tail_4", @@ -111,7 +114,8 @@ func _wobble_body(delta: float) -> void: target_pitch = clampf(-atan2(vel.y, flat_spd) * DP.f("aerial_pitch_scale"), -1.4, 1.4) _aerial_pitch = lerpf(_aerial_pitch, target_pitch, delta * DP.f("aerial_pitch_speed")) - _bull.rotation.x = _tilt_x + _aerial_pitch + _charge_pitch_curr = lerpf(_charge_pitch_curr, charge_pitch_target, delta * DP.f("charge_head_speed")) + _bull.rotation.x = _tilt_x + _aerial_pitch + _charge_pitch_curr _bull.rotation.z = _tilt_z diff --git a/debug_params.gd b/debug_params.gd index ed1a1db..f1911a5 100644 --- a/debug_params.gd +++ b/debug_params.gd @@ -53,6 +53,11 @@ func _register_all() -> void: _reg_f("Tail", "tail_body_radius", 0.35, 0.05, 2.0, 0.05) _reg_f("Tail", "tail_wag_freq", 4.0, 0.5, 15.0) _reg_f("Tail", "tail_wag_idle", 0.3, 0.0, 2.0, 0.05) + # ── Charge (both mouse buttons) ────────────────────────────────────────── + _reg_f("Charge", "bull_charge_accel", 20.0, 1.0, 200.0) + _reg_f("Charge", "bull_charge_max_speed", 22.0, 5.0, 100.0) + _reg_f("Charge", "charge_head_pitch", 0.3, 0.0, 1.2, 0.01) + _reg_f("Charge", "charge_head_speed", 5.0, 0.5, 20.0) # ── Body ────────────────────────────────────────────────────────────────── _reg_f("Body", "body_tilt_fwd", 0.015, 0.0, 0.1, 0.001) _reg_f("Body", "body_tilt_side", 0.01, 0.0, 0.1, 0.001) diff --git a/player.gd b/player.gd index 209e99e..b454a27 100644 --- a/player.gd +++ b/player.gd @@ -14,9 +14,11 @@ const HOOF_OFFSETS: Array = [ var _hoof_emitters: Array[CPUParticles3D] = [] var _legs: Node -var _kick_timer: float = 0.0 -var _was_on_floor: bool = false +var _kick_timer: float = 0.0 +var _was_on_floor: bool = false var _pre_slide_vel_y: float = 0.0 +var _charge_dir: Vector3 = Vector3.ZERO +var _both_held: bool = false enum DustState { NONE, WALK, CHARGE } var _dust_state: DustState = DustState.NONE @@ -177,18 +179,42 @@ func _physics_process(delta: float) -> void: var charging := Input.is_action_pressed(&"charge") var on_floor := is_on_floor() - # ── Left / right click thrust ───────────────────────────────────────────── - # Left click → thrust NE (forward-right diagonal) - # Right click → thrust NW (forward-left diagonal) - if Input.is_action_just_pressed(&"thrust_left") or Input.is_action_just_pressed(&"thrust_right"): + # ── Mouse button actions ────────────────────────────────────────────────── + # Both held → charge: lock direction, ramp speed, lower head + # Left only → thrust NE (forward-right diagonal) + # 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") + var both_held := left_held and right_held + + if both_held and not _both_held: var raw := cube_guy.global_transform.basis.z - var bull_fwd := Vector3(raw.x, 0.0, raw.z).normalized() - var bull_right := bull_fwd.cross(Vector3.UP) - if Input.is_action_just_pressed(&"thrust_left"): + _charge_dir = Vector3(raw.x, 0.0, raw.z).normalized() + + if both_held: + velocity.x += _charge_dir.x * DP.f("bull_charge_accel") * delta + velocity.z += _charge_dir.z * DP.f("bull_charge_accel") * delta + var flat_c := Vector2(velocity.x, velocity.z) + var spd_c := flat_c.length() + if spd_c > DP.f("bull_charge_max_speed"): + velocity.x *= DP.f("bull_charge_max_speed") / spd_c + velocity.z *= DP.f("bull_charge_max_speed") / spd_c + _legs.set(&"charge_pitch_target", DP.f("charge_head_pitch")) + else: + _legs.set(&"charge_pitch_target", 0.0) + if Input.is_action_just_pressed(&"thrust_left") and not right_held: + var raw := cube_guy.global_transform.basis.z + var bull_fwd := Vector3(raw.x, 0.0, raw.z).normalized() + var bull_right := bull_fwd.cross(Vector3.UP) _apply_thrust((bull_fwd + bull_right).normalized()) - else: + elif Input.is_action_just_pressed(&"thrust_right") and not left_held: + var raw := cube_guy.global_transform.basis.z + var bull_fwd := Vector3(raw.x, 0.0, raw.z).normalized() + var bull_right := bull_fwd.cross(Vector3.UP) _apply_thrust((bull_fwd - bull_right).normalized()) + _both_held = both_held + # Reset kick timer on landing so the first kick after a bounce is immediate if on_floor and not _was_on_floor and direction: _kick_timer = 0.0 @@ -196,7 +222,7 @@ func _physics_process(delta: float) -> void: # ── Periodic kick ───────────────────────────────────────────────────────── _kick_timer = maxf(0.0, _kick_timer - delta) - if direction and _kick_timer <= 0.0: + if direction and _kick_timer <= 0.0 and not both_held: _apply_kick(direction, charging) _kick_timer = DP.f("kick_interval")