(BEGINNER) need help with player controller & acceleration.

Godot Version

4.3

Question

I coded player movement and everything here by myself, its spaghettified as hell and I want to add acceleration and deacceleration to the character.
Heres the code:

extends CharacterBody2D
@onready var collision_shape_2d = $CollisionShape2D
@export var speed : float = 100
@export var jump_velocity : float = -150
@export var double_jump_velocity : float = -130
@onready var timer = $Timer
@onready var animated_sprite : AnimatedSprite2D = $AnimatedSprite2D
@onready var attack_area = $Attack_Area
@onready var timer_2 = $Timer2
@onready var player = $“.”

Get the gravity from the project settings to be synced with RigidBody nodes.

var gravity = ProjectSettings.get_setting(“physics/2d/default_gravity”)
var has_double_jumped : bool = false
var animation_locked : bool = false
var direction_locked : bool = false
var direction : Vector2 = Vector2.ZERO
var was_in_air : bool = false
var rolling : bool = false
var is_attacking : bool = false
var can_attack : bool = true

func _physics_process(delta):

print(direction_locked)
if not is_on_floor():
	if (animated_sprite.animation == "jump_loop" or "jump_start"):
		animated_sprite.offset.y = 2
	if (animated_sprite.animation == "attack"):
		animated_sprite.offset.y = 2
else:
	animated_sprite.offset.y = 0

$Attack_Area/CollisionShape2D2.disabled = true
if animated_sprite.flip_h == false:
	if is_attacking == true:
		$Attack_Area/CollisionShape2D.disabled = false
	else:
		$Attack_Area/CollisionShape2D.disabled = true
else:
	if is_attacking == true:
		$Attack_Area/CollisionShape2D2.disabled = false
	else:
		$Attack_Area/CollisionShape2D2.disabled = true
	
if rolling  or is_attacking== true:
	direction_locked = true
# Add the gravity.
if not is_on_floor():
	if not rolling:
		speed = 85
	velocity.y += gravity * delta
	was_in_air = true
else:
	has_double_jumped = false
	
	if was_in_air == true:
		land()
		
	was_in_air = false

# Handle Jump.
if Input.is_action_just_pressed("jump"):
	if is_on_floor():
		# Normal jump from floor
		jump()
	elif not has_double_jumped:
		# Double jump in air
		double_jump()
		

# Get the input direction and handle the movement/deceleration.
# As good practice, you should replace UI actions with custom gameplay actions.
if Input.is_action_just_pressed("attack"):
	attack()
if Input.is_action_just_pressed("roll"):
	roll()
if not direction_locked:
	direction = Input.get_vector("left", "right", "up", "down")

if direction.x != 0 && animated_sprite.animation != "jump_end":
	velocity.x = direction.x * speed
else:
	velocity.x = move_toward(velocity.x, 0, speed)

move_and_slide()
update_animation()
update_facing_direction()

func update_animation():

if not animation_locked:
	if not is_on_floor():
		animated_sprite.play("jump_loop")
	else:
		if direction.x != 0:
			animated_sprite.play("run")
		else:
			animated_sprite.play("idle")

func update_facing_direction():
if direction.x > 0:
animated_sprite.flip_h = true
elif direction.x < 0:
animated_sprite.flip_h = false

func jump():
if rolling == true:
jump_buffer()
if not direction_locked:
velocity.y = jump_velocity
animated_sprite.play(“jump_start”)
animation_locked = true
func jump_buffer():
await animated_sprite.animation_finished
jump()
func roll():
if is_on_floor() and direction.x != 0 and is_attacking == false:
player.set_collision_mask_value(2, true)
player.set_collision_mask_value(1, false)
animated_sprite.play(“roll”)
speed = 120
rolling = true
animation_locked = true
func double_jump():

velocity.y = double_jump_velocity
animated_sprite.play("jump_double")
if is_attacking == true:
	animation_locked = true
	direction_locked = false
has_double_jumped = true

func attack():
if not rolling:
if can_attack == true:
is_attacking = true
speed = 50
animated_sprite.play(“attack”)
can_attack = false
direction_locked = true
animation_locked = true
attack_cooldown()
func attack_cooldown():
timer.one_shot = true
timer.start(1)
await timer.timeout
can_attack = true
func land():
if not rolling and not is_attacking:
animated_sprite.play(“jump_end”)
animation_locked = true

func _on_animated_sprite_2d_animation_finished():
if([“jump_end”, “jump_start”, “jump_double”].has(animated_sprite.animation)):
animation_locked = false
direction_locked = false
speed = 100
if([“roll”].has(animated_sprite.animation)):
player.set_collision_mask_value(1, true)
player.set_collision_mask_value(2, false)
direction_locked = false
animation_locked = false
rolling = false
player.set_collision_layer_value(1, true)
speed = 100
if([“attack”].has(animated_sprite.animation)):
is_attacking = false
animation_locked = false
direction_locked = false
speed = 100

Ok, first of all: If you want people to read a big chunk of code, it’s a good idea to format it with syntax highlighting and indentation. Edit your post, select all of the code, and press the </> button. It’ll add three backticks ( ``` ) before and after your code, which tells the forum “this is code, please display it as such”.

For acceleration, it really depends on how complex you want it to be… But I notice that right now you are doing:

velocity.x = direction.x * speed

And you could probably change that to something like:

velocity.x = move_toward(velocity.x, direction.x * speed, acceleration * delta)

With acceleration being a variable that defines how much the velocity is allowed to change over a second.

2 Likes

the amount of code seems intimidating but I am actually only interested in seeing parts of your code in relation to setting your character’s velocity of which this seems relevant:

if direction.x != 0 && animated_sprite.animation != "jump_end":
	velocity.x = direction.x * speed
else:
	velocity.x = move_toward(velocity.x, 0, speed)

right from the start, I don’t see you factoring the delta variable into the equation which would have been vital to introducing proper acceleration to your movement.

Going along with @tayacan’s proposal seems valid.

1 Like

Yes, delta should be factored into the acceleration, but not to the velocity itself, since move_and_slide does that for us.

2 Likes