I'm attempting to make a simple 2D game in Godot 4.0 and I am having trouble getting my player to jump. I am just trying to have the character jump when pressing W which is "jump." I'm very new to Godot and I tried searching for ways to implement it and they all generally used velocity.y = jumpForce (or whatever your variable is).
When pressing W my character does not move but it successfully prints "trying to jump." The gravity and side to side movement works fine.
Here is my code, any help is appreciated.
extends CharacterBody2D
#var motion = Vector2(0,0)
var speed = 5
var gravity = 5
const jumpForce = -400
#var maxSpeed = 2000
#var frictionAir = 0.95
#var frictionGround = 0.85
#var canJump = false
#var isOnFloor = false
# Called when the node enters the scene tree for the first time.
func _ready():
pass # Replace with function body.
func _physics_process(_delta):
if Input.is_action_pressed("ui_right"):
position.x += 1*speed
elif Input.is_action_pressed("ui_left"):
position.x -= 1*speed
#isOnFloor = is_on_floor()
if Input.is_action_just_pressed("jump"):
print("trying to jump")
velocity.y = jumpForce
else:
move_and_collide(Vector2(0, 1*gravity))
# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(_delta):
pass
I believe the issue is on the last line of your physics_process function.
move_and_collide(Vector2(0, 1*gravity))
If you pass a in a vector to move_and_collide, it'll move your character by that vector every position.
Currently, it's trying to move your character by (0, 1*gravity) every frame. This is probably not what you want, as it's just moving your character down by 5px every frame.
Most people will use move_and_collide(velocity * delta)
, as this moves the player by however large their velocity is every frame (this is what the definition of a velocity is).
If you do this, then instead of modifying the position directly
position.x += 1*speed
,
you can just modify the velocity:
velocity.x = 1*speed
This lets godot handle the collision later in move_and_collide().
And for gravity, just put this line somewhere in the physics process:
velocity.y += gravity
(This is basically how acceleration is used in physics)
Here's a version of your function that I think will work:
func _physics_process(_delta):
velocity.x = 0
# If you'd like to implement a friction force, you could do it here.
# velocity.x = 0 is basically infinite friction.
# without this line, your player would slide forever.
if Input.is_action_pressed("ui_right"):
velocity.x = 1*speed
elif Input.is_action_pressed("ui_left"):
velocity.x = -1*speed
#isOnFloor = is_on_floor()
if Input.is_action_just_pressed("jump"):
print("trying to jump")
velocity.y = jumpForce
else:
velocity.y += gravity # adding gravity
move_and_collide(velocity * _delta)
# this doesn't need to be in the else.
# If it is, then your player will freeze whenever you press "jump".
Next thing to add would be checking if the player is on the floor before jumping, and it looks like you've started doing that!
Also, if you run into the problem where your player is frozen when touching a platform / wall, try replacing move_and_collide(velocity * _delta)
with move_and_slide()
Good luck!