My existing code looks different because of the simpler way to stomp.
Despite the code from this video the snapping on the slope does not work as it should. The player still jumps automatically when reaching the top of the slope.
My current Player.gd:
extends Actor class_name Player export var stomp_impulse: = 1000.0 func _on_StompDetector_area_entered(area: Area2D) -> void: _velocity = calculate_stomp_velocity(_velocity, stomp_impulse) func _on_EnemyDetector_body_entered(body: Node) -> void: queue_free() func _physics_process(delta: float) -> void: var is_jump_interrupted: = Input.is_action_just_released("jump") and _velocity.y < 0 var direction: = get_direction() _velocity = calculate_move_direction(_velocity, direction, speed, is_jump_interrupted) var snap: = Vector2.DOWN * 80.0 if direction.y == 0.0 else Vector2.ZERO _velocity.y = move_and_slide_with_snap( _velocity, snap, FLOOR_NORMAL, true, 4, PI / 3.0).y for i in get_slide_count(): var collision := get_slide_collision(i) var collider := collision.collider var is_stomping := ( collider is Enemy and is_on_floor() and collision.normal.dot(Vector2.UP) > 0.5 ) if is_stomping: _velocity.y = -stomp_impulse (collider as Enemy).kill() func get_direction() -> Vector2: return Vector2( Input.get_action_strength("ui_right") - Input.get_action_strength("ui_left"), -1.0 if Input.is_action_just_pressed("ui_jump") and is_on_floor() else 1.0 ) func calculate_move_direction( linear_velocity: Vector2, direction: Vector2, speed: Vector2, is_jump_interrupted: bool ) -> Vector2: var out: = linear_velocity out.x = speed.x * direction.x out.y += gravity * get_physics_process_delta_time() if direction.y == -1.0: out.y = speed.y * direction.y if is_jump_interrupted: out.y = 0 return out func calculate_stomp_velocity(linear_velocity: Vector2, impulse: float) -> Vector2: var out: = linear_velocity out.y = -impulse return out
You can try to play with two parameters:
The number "4" below, the number of slides. I don't remember if I showed this in the video but reducing it to 1 or 2 on the ground could help. It's the max number of times the character may move and collide again after a collision.
The other parameter is the slope angle, PI / 3.0. If your slope is about the same angle, you'll get some issues.
Could you try and tell me if it helps?
move_and_slide_with_snap( _velocity, snap, FLOOR_NORMAL, true, 4, PI / 3.0 )
Reducing the number of slides to 2 does not change the automatic jumping of the player. After further reducing to 1, the player moves very slowly on the ground, but the automatic jumping when reaching the top of the slope is gone.
In this case, I would need your Godot project to solve the issue. Could you zip it and upload it somewhere?
You can download the Godot project from the following URL:
I see why. The condition for your snap vector to point down is never true:
var snap: = Vector2.DOWN * 80.0 if direction.y == 0.0 else Vector2.ZERO
So your never snap to the floor.
You need to change the condition to
if is_equal_approx(direction.y, 1.0)
Note I'm using the function is_equal_approx() here instead of ==, a function added in Godot to account for processor rounding mistakes with floating point values. Using this function is robust while checking for inequality can lead to weird bugs.
This is because get_direction() returns either -1.0 or 1.0 for the y axis,so it's never equal to 0.0:
func get_direction() -> Vector2: return Vector2( Input.get_action_strength("ui_right") - Input.get_action_strength("ui_left"), -1.0 if Input.is_action_just_pressed("ui_jump") and is_on_floor() else 1.0 )
Great! Using the `is_equal_approx()` function has solved the problem.
Many thanks for your detailed explanation about the problem and how to fix it.
I ran into this same issue, but I used:
var snap: = Vector2.DOWN * 50.0 if direction.y >= 0.0 else Vector2.ZERO
This seems to work, as my direction.y should only be >= 0.0 if jumping, correct? Is there a reason I shouldn't use this?
My jump code is still the original as I have not yet changed it based on the "simpler way to stomp" code.