Slopes "momentum" in 2D

Godot 4.5

Hi! I’m new to this engine, but I’m getting the hang of it trying to recreate Sonic the Hedgehog from the Master System! My problem is, I don’t know how to make it slow down when going up ramps and speed up a lot when going down. Could you help me? If you add anything to the code, please use my code and send me the new lines where they go.

the code in GDscript:

extends CharacterBody2D


@export var animaciones: AnimatedSprite2D
var MAX_SPEED: float = 240.0
var ACELERATION: float = 5.625
var DESACELERATION: float = 25.0
var JUMP_VELOCITY: float = -390.0
var GRAVITY: float = 13.125
var IDLE_TIME: float = 0.0
var UP_DOWN: float = 0
var SPINING: bool = false
var JUMPING: bool = false


func _physics_process(delta: float) -> void:
	# Add the gravity.
	if !is_on_floor():
		velocity += get_gravity() * delta
		SPINING = false
	
	# Handle jump.
	if Input.is_action_just_pressed("ui_accept") and is_on_floor():
		velocity.y = JUMP_VELOCITY
	
	# Animation of jumping.
	if is_on_floor():
		JUMPING = false
	elif velocity.y < 0:
		JUMPING = true
	
	if  SPINING == false:
		if !Input.is_action_pressed("ui_up") and !Input.is_action_pressed("ui_down") or abs(velocity.x) > 0:
			UP_DOWN = 0
			if Input.is_action_pressed("ui_down"):
				if abs(velocity.x) > 0:
					SPINING = true
			
			if Input.is_action_pressed("ui_right"):
				if velocity.x < 0:
					velocity.x += DESACELERATION
					if velocity.x > 0:
						velocity.x = 0
				else:
					velocity.x += ACELERATION
				if velocity.x > MAX_SPEED:
					velocity.x = MAX_SPEED
			elif Input.is_action_pressed("ui_left"):
				if velocity.x > 0:
					velocity.x -= DESACELERATION
					if velocity.x < 0:
						velocity.x = 0
				else:
					velocity.x -= ACELERATION
				if velocity.x < MAX_SPEED * -1:
					velocity.x = MAX_SPEED * -1
			else:
				if velocity.x > 0:
					velocity.x -= ACELERATION
					if velocity.x < 0:
						velocity.x = 0
				elif velocity.x < 0:
					velocity.x += ACELERATION
					if velocity.x > 0:
						velocity.x = 0
		else:
			if Input.is_action_pressed("ui_up"):
				UP_DOWN = 1
			if Input.is_action_pressed("ui_down"):
				UP_DOWN = -1
	else:
		if velocity.x > 0:
			velocity.x -= ACELERATION
			if velocity.x < 0:
				velocity.x = 0
		elif velocity.x < 0:
			velocity.x += ACELERATION
			if velocity.x > 0:
				velocity.x = 0 
		if velocity.x == 0:
			SPINING = false
	
	if velocity.x > 0:
		animaciones.flip_h = false
	if velocity.x < 0:
		animaciones.flip_h = true
	
	
	
	if JUMPING == true:
		IDLE_TIME = 0.0
		animaciones.play("Ball")
	elif abs(velocity.x) > 1:
		IDLE_TIME = 0.0
		if SPINING:
			animaciones.play("Ball")
		else:
			if velocity.x > 0 and Input.is_action_pressed("ui_left") or velocity.x < 0 and Input.is_action_pressed("ui_right"):
				animaciones.play("Skid")
			else:
					if abs(velocity.x) > 200:
						animaciones.play("Run")
					else:
						animaciones.play("Walk")
	else:
		if abs(UP_DOWN) > 0:
			if UP_DOWN > 0:
				animaciones.play ("Up")
			elif UP_DOWN < 0:
				animaciones.play ("Down")
		else:
			IDLE_TIME += delta
			if IDLE_TIME > 6.0:
				if IDLE_TIME > 6.5:
					animaciones.play("Wait")
					IDLE_TIME = 6.5
				else:
					animaciones.play("Wait_Start")
			else:
				animaciones.play("Idle")
	
	move_and_slide()

I think you should look into implementing a State Machine to simplify your current system, otherwise it’ll be hard to add more states without breaking everything else.
I can recommend @dragonforge-dev’s State Machine:

On a side note, you can maybe reach out to @Sonic_Battle_2, as you both seem to be working on Sonic related projects, you might want to potentially join forces or just collaborate.

2 Likes

im going to try it, thanks :slight_smile:

1 Like