No Pushback on Wall Jump

Godot Version

4.2.2

Question

Hi! I’ve been trying to implement a wall jump into my prototype. I followed many tutorials and finally found something that works only partially for me.
The pushback on the x-axis doesn’t work. I’ve been reading a lot about it, and it seems there is something up with move_and_slide() and its placement, but no solution works for my code.
I would really appreciate any help or guidance on that topic.

extends CharacterBody2D


const SPEED = 130.0
var JUMP_VELOCITY = -360.0
const gravity = 1000
const fall_gravity = 1200

var is_wall_slide = false
var wall_jump_power = 10000
const wall_slide_gravity = 50

@onready var animated_sprite = $AnimatedSprite2D
@onready var all_interactions = []
@onready var interactLabel = $"interaction/InteractLabel"

# Jump Curve
func get_gravity(velocity :Vector2):
	if velocity.y < 0:
		return gravity
	else:
		return fall_gravity

func _physics_process(delta):
	
	# Interaction
	if Input.is_action_just_pressed("interact"):
		execute_interaction()

	# Add the gravity.
	if not is_on_floor():
		velocity.y += get_gravity(velocity) * delta
	
	# Handle jump.
	if Input.is_action_just_pressed("jump"): 
		if is_on_floor():
			velocity.y = JUMP_VELOCITY
		if  is_on_wall() and Input.is_action_pressed("move_left"):
			velocity.y = JUMP_VELOCITY
			velocity.x = -wall_jump_power
		
		if  is_on_wall() and Input.is_action_pressed("move_right"):
			velocity.y = JUMP_VELOCITY
			velocity.x = wall_jump_power
			
	# Release Jump
	if Input.is_action_just_released("jump") and velocity.y < 0:
		velocity.y = JUMP_VELOCITY / 4
		
	# Get the input direction: -1, 0, 1.
	var direction = Input.get_axis("move_left", "move_right")
	
	if direction:
		velocity.x = move_toward(velocity.x, direction * SPEED, 36.0)
	else:
		velocity.x = move_toward(velocity.x, 0, 36)

	move_and_slide()
	wall_slide(delta)
	
	# Flip the spirte
	if direction > 0:
		animated_sprite.flip_h = false
	elif direction < 0:
		animated_sprite.flip_h = true
	
	# Play animation
	if is_on_floor():
		if Input.is_key_pressed(KEY_I):
			animated_sprite.play("idle_suit")
		else: if direction == 0:
			animated_sprite.play("idle")
		else:
			animated_sprite.play("run")
	else:
		animated_sprite.play("jump")
		
	if is_wall_slide:
		animated_sprite.play("wall_land_right")

func wall_slide(delta):
	# Wall Slide
	if is_on_wall() and !is_on_floor(): 
		if Input.is_action_pressed("move_left") or Input.is_action_pressed("move_right"):
			is_wall_slide = true
		else:
			is_wall_slide = false
	else:
		is_wall_slide = false
		
	if is_wall_slide:
		velocity.y += (wall_slide_gravity * delta)
		velocity.y = min(velocity.y, wall_slide_gravity)




#interactions

func _on_area_2d_area_entered(area):
	all_interactions.insert(0, area)
	update_interactions()


func _on_area_2d_area_exited(area):
	all_interactions.erase(area)
	update_interactions()
	
func update_interactions():
	if all_interactions:
		interactLabel.text = all_interactions[0].interact_label
	else:
		interactLabel.text = ""

func execute_interaction():
	if all_interactions:
		var  cur_interaction = all_interactions[0]
		match  cur_interaction.interact_type:
			"swap_weapon": $Weapon.set_texture(load("res://assets/items/weapons/crossbow.png"))

func _physics_process(delta):
    # ... (existing code)

    # Handle jump.
    if Input.is_action_just_pressed("jump"): 
        if is_on_floor():
            velocity.y = JUMP_VELOCITY
        elif is_on_wall():
            velocity.y = JUMP_VELOCITY
            velocity.x = get_wall_normal().x * wall_jump_power

    # ... (rest of existing code)

Do these changes help?

1 Like

They actually do! It works smoothly now, without problems it seems.
Thank you so much! <3
Could you elaborate on why get_wall_normal works here?

1 Like

Using the wall normal simplifies the code a bit (depending on how you reallt want the mechanic to work).

The normal is perpedicular to the wall, so the x portion will be positove or negative based on that (assuming all your walls are vertical, it will be +/- 1). This gives you the direction you need to move jumping “off” the wall.

The only possible draw back here is if the wall isnt completely vertical, the x portion of the normal will be a little smaller (because some of the normal will be in the y direction). But that is not necessarily a drawback.

1 Like

I see, I think I get a little bit of an idea on how this works. I’ll surely discover more as I learn.
Thank you so much again!

Also, did you log the input when jumping? It is possible the controls weren’t registering exactly when and exactly as you anticipated.

Try doing a couple of print statements to see what is going on in your code when you wall jump.

1 Like

I was advised to do that by someone actually. I’ll remember to use it in the future. It surely comes in handy when troubleshooting

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.