Wall jumping pushback not working

Godot Version

4.3

Question

I’m trying to do a 2d game plataformer and I’m trying to add a wall jumping mechanic to the game, I use raycasting to know if I’m hitting a wall or not. The jump works but I want it to do a little pushback that it only does when im not pressing left or right and that’s whats not working:

Here’s the code:
extends CharacterBody2D

@onready var rayWall = $RayWall

const SPEED = 600.0
const JUMP_VELOCITY = -500.0
const WALL_PUSHBACK_X = 2000
const WALL_PUSHBACK_Y = -400
const WALL_SLIDE_MAX = 50

var jumping = 0
var debug_counter = 0

func _physics_process(delta: float) → void:
var direction := Input.get_axis(“ui_left”, “ui_right”)
var wall_normal = get_wall_normal()

#DEBUGGING-----------------------------------------
print("----",debug_counter,"----")
print("DIR - ",direction)
print("VEL - ",velocity)
print("JUMP - ",jumping)
debug_counter += 1
#---------------------------------------------------	

#GRAVITY HANDLING
if not is_on_floor():
	velocity += get_gravity() * delta
else:
	jumping = 0 #Reset jumping when touching ground


if Input.is_action_just_pressed("ui_accept"):
	if is_on_floor():
		velocity.y = JUMP_VELOCITY
		jumping = 1
	elif wall_colider():
		velocity = wall_normal * WALL_PUSHBACK_X
		velocity.y = WALL_PUSHBACK_Y
	elif jumping == 1:
		velocity.y = JUMP_VELOCITY
		jumping = 0

		
#WALL SLIDING
if wall_colider():
	velocity.y = min(velocity.y, WALL_SLIDE_MAX)
	jumping = 1
	
#HANDLE X DIRECTION
if direction:
	velocity.x = direction * SPEED
	if direction == 1:
		rayWall.scale.x = 1
	elif direction == -1:
		rayWall.scale.x = -1
else:
	velocity.x = move_toward(velocity.x, 0, SPEED)


move_and_slide()

func wall_colider():
return rayWall.is_colliding()

If your player is holding a direction, their x velocity is instantly set to SPEED in that direction. If they aren’t then the x velocity is reduced to 0 by SPEED per-frame.

The 2D platformer template has both of these bugs baked-in, no acceleration and a misuse of move_toward, as a bonus you do not need to check if direction since when direction is zero (the else:) the math ends up as 0 * SPEED, which is zero, without the check the game would run exactly the same.

To adapt this code for acceleration based movement you need to look out for instantly setting velocity, instead only using move_toward with acceleration and delta to be per-second instead of per-frame.

# increase to max speed in 1/8th of a second
const ACCELERATION = SPEED * 8


# no if direction needed
velocity.x = move_toward(velocity.x, direction * SPEED, ACCELERATION * delta)

Make sure to tweak the acceleration value.

1 Like

Thanks so much