leg jump swap ani fix
This commit is contained in:
@@ -73,25 +73,7 @@ func update(delta: float) -> void:
|
|||||||
machine.notify_landed(fall_speed)
|
machine.notify_landed(fall_speed)
|
||||||
|
|
||||||
# Bunny hop: if jump was buffered or pressed on landing frame
|
# Bunny hop: if jump was buffered or pressed on landing frame
|
||||||
if (machine.input_jump_pressed or machine.jump_buffer_time > 0.0) and machine.jump_cooldown_timer <= 0.0:
|
if _try_bunny_hop():
|
||||||
var land_speed := Vector3(player.velocity.x, 0.0, player.velocity.z).length()
|
|
||||||
var bhop_speed := maxf(land_speed, minf(land_speed + params.bunny_hop_speed_gain, params.bunny_hop_speed_cap))
|
|
||||||
# Maintain horizontal direction, boost speed
|
|
||||||
var hdir := Vector3(player.velocity.x, 0.0, player.velocity.z)
|
|
||||||
if hdir.length_squared() > 0.01:
|
|
||||||
hdir = hdir.normalized()
|
|
||||||
else:
|
|
||||||
hdir = machine.wish_dir_world
|
|
||||||
player.velocity.x = hdir.x * bhop_speed
|
|
||||||
player.velocity.z = hdir.z * bhop_speed
|
|
||||||
player.velocity.y = params.jump_velocity * params.bunny_hop_impulse
|
|
||||||
machine.current_jump_count = 1
|
|
||||||
machine.on_ground = false
|
|
||||||
machine.jump_buffer_time = 0.0
|
|
||||||
machine.register_chain_mechanic("bunny_hop")
|
|
||||||
machine.jump_cooldown_timer = params.jump_cooldown
|
|
||||||
if player.jump_player:
|
|
||||||
player.jump_player.play()
|
|
||||||
# Stay in air state
|
# Stay in air state
|
||||||
return
|
return
|
||||||
|
|
||||||
@@ -109,6 +91,7 @@ func update(delta: float) -> void:
|
|||||||
player.double_jump_player.play()
|
player.double_jump_player.play()
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
||||||
# ── Wall interaction (Run, Climb, Vault) ──────────────────────────────
|
# ── Wall interaction (Run, Climb, Vault) ──────────────────────────────
|
||||||
if machine.input_dir.length() > 0.1 and machine.input_dir.y <= 0.0 and machine.wall_cooldown_timer <= 0.0:
|
if machine.input_dir.length() > 0.1 and machine.input_dir.y <= 0.0 and machine.wall_cooldown_timer <= 0.0:
|
||||||
var fwd_wall = machine.detect_wall_forward()
|
var fwd_wall = machine.detect_wall_forward()
|
||||||
@@ -143,3 +126,35 @@ func update(delta: float) -> void:
|
|||||||
if machine.input_dash and machine.can_dash():
|
if machine.input_dash and machine.can_dash():
|
||||||
machine.switch_to("dash")
|
machine.switch_to("dash")
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
||||||
|
func _try_bunny_hop() -> bool:
|
||||||
|
# Held jump is intentionally accepted here so landing can immediately start
|
||||||
|
# the next hop without spending a frame in Ground. It is still a distinct
|
||||||
|
# takeoff and must emit the same event as every other grounded jump; the
|
||||||
|
# player model uses that event to alternate its complete airborne pose.
|
||||||
|
if not (machine.input_jump_pressed or machine.jump_buffer_time > 0.0) \
|
||||||
|
or machine.jump_cooldown_timer > 0.0:
|
||||||
|
return false
|
||||||
|
var player := machine.player
|
||||||
|
var land_speed := Vector3(player.velocity.x, 0.0, player.velocity.z).length()
|
||||||
|
var bhop_speed := maxf(land_speed, minf(
|
||||||
|
land_speed + params.bunny_hop_speed_gain, params.bunny_hop_speed_cap))
|
||||||
|
# Maintain horizontal direction, boost speed.
|
||||||
|
var hdir := Vector3(player.velocity.x, 0.0, player.velocity.z)
|
||||||
|
if hdir.length_squared() > 0.01:
|
||||||
|
hdir = hdir.normalized()
|
||||||
|
else:
|
||||||
|
hdir = machine.wish_dir_world
|
||||||
|
player.velocity.x = hdir.x * bhop_speed
|
||||||
|
player.velocity.z = hdir.z * bhop_speed
|
||||||
|
player.velocity.y = params.jump_velocity * params.bunny_hop_impulse
|
||||||
|
machine.current_jump_count = 1
|
||||||
|
machine.on_ground = false
|
||||||
|
machine.jump_buffer_time = 0.0
|
||||||
|
machine.register_chain_mechanic("bunny_hop")
|
||||||
|
machine.jump_cooldown_timer = params.jump_cooldown
|
||||||
|
machine.movement_event.emit("jump", {"kind": "bunny_hop"})
|
||||||
|
if player.jump_player:
|
||||||
|
player.jump_player.play()
|
||||||
|
return true
|
||||||
|
|||||||
@@ -63,6 +63,7 @@ func update(delta: float) -> void:
|
|||||||
player.velocity = vel
|
player.velocity = vel
|
||||||
machine.jump_cooldown_timer = params.jump_cooldown
|
machine.jump_cooldown_timer = params.jump_cooldown
|
||||||
machine.register_chain_mechanic("grapple_jump")
|
machine.register_chain_mechanic("grapple_jump")
|
||||||
|
machine.movement_event.emit("jump", {"kind": "grapple_jump"})
|
||||||
machine.switch_to("air")
|
machine.switch_to("air")
|
||||||
if player.jump_player:
|
if player.jump_player:
|
||||||
player.jump_player.play()
|
player.jump_player.play()
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ func run_all() -> void:
|
|||||||
var tests := [
|
var tests := [
|
||||||
"test_states_register_and_initialize",
|
"test_states_register_and_initialize",
|
||||||
"test_do_jump_sets_velocity_and_counters",
|
"test_do_jump_sets_velocity_and_counters",
|
||||||
|
"test_held_jump_bunny_hops_emit_each_takeoff",
|
||||||
"test_double_jump_emits_jet_event",
|
"test_double_jump_emits_jet_event",
|
||||||
"test_wall_run_preserves_fast_entry_speed",
|
"test_wall_run_preserves_fast_entry_speed",
|
||||||
"test_wall_run_entry_keeps_some_upward_momentum",
|
"test_wall_run_entry_keeps_some_upward_momentum",
|
||||||
@@ -129,6 +130,40 @@ func test_do_jump_sets_velocity_and_counters() -> void:
|
|||||||
_expect(not sm.on_ground, "no longer grounded")
|
_expect(not sm.on_ground, "no longer grounded")
|
||||||
|
|
||||||
|
|
||||||
|
func test_held_jump_bunny_hops_emit_each_takeoff() -> void:
|
||||||
|
var jump_events: Array[String] = []
|
||||||
|
var controller := PlayerMovementController.new()
|
||||||
|
controller._machine = sm
|
||||||
|
sm.movement_event.connect(func(event_name: String, data: Dictionary) -> void:
|
||||||
|
if event_name == "jump":
|
||||||
|
jump_events.append(String(data.get("kind", "jump")))
|
||||||
|
controller._on_movement_event(event_name, data)
|
||||||
|
)
|
||||||
|
var air = sm.states["air"]
|
||||||
|
sm.input_jump_pressed = true
|
||||||
|
fake_player.velocity = Vector3(0.0, 0.0, -params.walk_speed)
|
||||||
|
var variants: Array[String] = []
|
||||||
|
|
||||||
|
# Start with an ordinary ground jump, then keep Space held through three
|
||||||
|
# direct Air -> Air bunny hops. No intervening motion state is involved.
|
||||||
|
sm.do_jump()
|
||||||
|
variants.append(controller._visual_animation_state("air", params.walk_speed))
|
||||||
|
for hop in 3:
|
||||||
|
sm.jump_cooldown_timer = 0.0
|
||||||
|
sm.notify_landed(0.0)
|
||||||
|
_expect(air._try_bunny_hop(),
|
||||||
|
"held jump starts bunny hop %d" % (hop + 1))
|
||||||
|
variants.append(controller._visual_animation_state(
|
||||||
|
"air", params.walk_speed))
|
||||||
|
|
||||||
|
_eq(jump_events, ["jump", "bunny_hop", "bunny_hop", "bunny_hop"],
|
||||||
|
"every held-space bunny hop emits a jump takeoff")
|
||||||
|
_eq(variants, ["air_alt", "air", "air_alt", "air"],
|
||||||
|
"ground jump and consecutive bunny hops alternate leg variants")
|
||||||
|
controller._machine = null
|
||||||
|
controller.free()
|
||||||
|
|
||||||
|
|
||||||
func test_double_jump_emits_jet_event() -> void:
|
func test_double_jump_emits_jet_event() -> void:
|
||||||
var events := []
|
var events := []
|
||||||
sm.movement_event.connect(func(ev, data): events.append([ev, data]))
|
sm.movement_event.connect(func(ev, data): events.append([ev, data]))
|
||||||
|
|||||||
Reference in New Issue
Block a user