Files
godot-demo-projects/2d/skeleton/player/player.gd
2025-10-11 05:03:59 -07:00

103 lines
2.9 KiB
GDScript

class_name Player
extends CharacterBody2D
# Keep this in sync with the AnimationTree's state names.
const States = {
IDLE = "idle",
WALK = "walk",
RUN = "run",
FLY = "fly",
FALL = "fall",
}
const WALK_SPEED = 200.0
const ACCELERATION_SPEED = WALK_SPEED * 6.0
const JUMP_VELOCITY = -400.0
## Maximum speed at which the player can fall.
const TERMINAL_VELOCITY = 400
var falling_slow: bool = false
var falling_fast: bool = false
var no_move_horizontal_time := 0.0
@onready var gravity := float(ProjectSettings.get_setting("physics/2d/default_gravity"))
@onready var sprite: Node2D = $Sprite2D
@onready var sprite_scale := sprite.scale.x
func _ready() -> void:
$AnimationTree.active = true
func _physics_process(delta: float) -> void:
var is_jumping: bool = false
if Input.is_action_just_pressed(&"jump"):
is_jumping = try_jump()
elif Input.is_action_just_released(&"jump") and velocity.y < 0.0:
# The player let go of jump early, reduce vertical momentum.
velocity.y *= 0.6
# Fall.
velocity.y = minf(TERMINAL_VELOCITY, velocity.y + gravity * delta)
var direction := Input.get_axis(&"move_left", &"move_right") * WALK_SPEED
velocity.x = move_toward(velocity.x, direction, ACCELERATION_SPEED * delta)
if no_move_horizontal_time > 0.0:
# After doing a hard fall, don't move for a short time.
velocity.x = 0.0
no_move_horizontal_time -= delta
if not is_zero_approx(velocity.x):
if velocity.x > 0.0:
sprite.scale.x = 1.0 * sprite_scale
else:
sprite.scale.x = -1.0 * sprite_scale
move_and_slide()
# After applying our motion, update our animation to match.
# Calculate falling speed for animation purposes.
if velocity.y >= TERMINAL_VELOCITY:
falling_fast = true
falling_slow = false
elif velocity.y > 300:
falling_slow = true
if is_jumping:
$AnimationTree["parameters/jump/request"] = AnimationNodeOneShot.ONE_SHOT_REQUEST_FIRE
if is_on_floor():
# Most animations change when we run, land, or take off.
if falling_fast:
$AnimationTree["parameters/land_hard/request"] = AnimationNodeOneShot.ONE_SHOT_REQUEST_FIRE
no_move_horizontal_time = 0.4
elif falling_slow:
$AnimationTree["parameters/land/request"] = AnimationNodeOneShot.ONE_SHOT_REQUEST_FIRE
if abs(velocity.x) > 50:
$AnimationTree["parameters/state/transition_request"] = States.RUN
$AnimationTree["parameters/run_timescale/scale"] = abs(velocity.x) / 60
elif velocity.x:
$AnimationTree["parameters/state/transition_request"] = States.WALK
$AnimationTree["parameters/walk_timescale/scale"] = abs(velocity.x) / 12
else:
$AnimationTree["parameters/state/transition_request"] = States.IDLE
falling_fast = false
falling_slow = false
else:
if velocity.y > 0:
$AnimationTree["parameters/state/transition_request"] = States.FALL
else:
$AnimationTree["parameters/state/transition_request"] = States.FLY
func try_jump() -> bool:
if is_on_floor():
velocity.y = JUMP_VELOCITY
return true
return false