Last active
November 1, 2024 16:11
-
-
Save juanibiapina/34795ec63a0b2a869c4d7a45c3709dcc to your computer and use it in GitHub Desktop.
Platformer Controller
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
extends CharacterBody2D | |
const floor_move_speed_max: float = 400.0 | |
const floor_move_acceleration: float = 2000 | |
const floor_friction: float = 2000 | |
const jump_min_height: float = 50 | |
const jump_max_height: float = 200 | |
const jump_time_to_apex: float = 0.5 | |
const air_move_speed_max: float = 400.0 | |
const air_move_acceleration: float = 2000 | |
const air_friction: float = 800 | |
const fall_max_speed: float = 3000 | |
# Derived variables | |
var jump_speed_max: float | |
var jump_speed_min: float | |
var gravity: float | |
# State variables | |
var state: Callable = fall_state | |
var remaining_air_jumps = 1 | |
func _ready(): | |
jump_speed_max = 2 * jump_max_height / jump_time_to_apex | |
jump_speed_min = lerpf(0, jump_speed_max, jump_min_height / jump_max_height) | |
gravity = (2 * jump_max_height) / (jump_time_to_apex * jump_time_to_apex) | |
func _physics_process(delta: float) -> void: | |
state.call(delta) | |
move_and_slide() | |
# States | |
func floor_state(delta: float): | |
if is_on_floor(): | |
try_jump() | |
floor_control(delta) | |
else: | |
change_to_fall_state() | |
func jump_state(delta: float): | |
if is_jump_over(): | |
change_to_fall_state() | |
else: | |
if Input.is_action_just_released("jump"): | |
jump_cutoff() | |
apply_gravity(delta) | |
air_control(delta) | |
try_air_jump() | |
func fall_state(delta: float): | |
if is_on_floor(): | |
change_to_floor_state() | |
else: | |
apply_gravity(delta) | |
air_control(delta) | |
try_air_jump() | |
# Helpers | |
func try_jump(): | |
if Input.is_action_just_pressed("jump"): | |
change_to_jump_state() | |
func change_to_jump_state(): | |
state = jump_state | |
velocity.y = -jump_speed_max | |
func jump_cutoff(): | |
if velocity.y < -jump_speed_min: | |
velocity.y = -jump_speed_min | |
func try_air_jump(): | |
if Input.is_action_just_pressed("jump") and can_air_jump(): | |
air_jump() | |
func can_air_jump(): | |
return remaining_air_jumps > 0 | |
func air_jump(): | |
change_to_jump_state() | |
remaining_air_jumps -= 1 | |
func change_to_floor_state(): | |
state = floor_state | |
remaining_air_jumps = 1 | |
func change_to_fall_state(): | |
state = fall_state | |
func apply_gravity(delta): | |
velocity.y = move_toward( | |
velocity.y, | |
fall_max_speed, | |
gravity * delta | |
) | |
func floor_control(delta: float): | |
var direction := Input.get_axis("move_left", "move_right") | |
if direction: | |
velocity.x = move_toward(velocity.x, floor_move_speed_max * sign(direction), floor_move_acceleration * delta) | |
else: | |
velocity.x = move_toward(velocity.x, 0, floor_friction * delta) | |
func air_control(delta): | |
var direction := Input.get_axis("move_left", "move_right") | |
if direction: | |
velocity.x = move_toward(velocity.x, air_move_speed_max * sign(direction), air_move_acceleration * delta) | |
else: | |
velocity.x = move_toward(velocity.x, 0, air_friction * delta) | |
func is_jump_over(): | |
return velocity.y >= 0 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment