hello peoples, ive been working on a godot project for a bit now, and have the basics done, such as player movement, and i dont have very many friends irl that can give me feedback other than “i wish i could move faster” does anyone have any advice, tips, or feedback on my gdscript, things i can improve, or anything?
the script itself:
extends CharacterBody2D
const SPEED: float = 115.0
const SWIM_SPEED: float = 70.0
const JUMP_FORCE: float = -210.0
const GRAVITY: float = 1000.0
const DASH_SPEED: float = 250.0
const DASH_DURATION: float = 0.15
const COYOTE_TIME: float = 0.12
const DASH_COOLDOWN: float = 0.6
enum State { NORMAL, JUMPING, DASHING, SWIMMING }
@onready var body: AnimatedSprite2D = $PlayerRoot/body
@onready var head: AnimatedSprite2D = $PlayerRoot/head
@onready var mask: AnimatedSprite2D = $PlayerRoot/mask
@onready var particles: AnimatedSprite2D = $PlayerRoot/particles
@onready var shadow: Sprite2D = $Shadow
@onready var object_hitbox: CollisionShape2D = $ObjectHitbox
@onready var feet: Node2D = $Feet
@onready var water_layers := get_tree().get_nodes_in_group("water")
@onready var ground_layers := get_tree().get_nodes_in_group("ground")
var state: State = State.NORMAL
var facing_direction: Vector2 = Vector2.DOWN
var can_dash: bool = true
var in_water: bool = false
var jump_velocity: float = 0.0
var coyote_timer: float = 0.0
var dash_cooldown_timer: float = 0.0
var dash_timer: float = 0.0
var dash_velocity: Vector2 = Vector2.ZERO
var last_feet_pos: Vector2 = Vector2.INF
# WATER DETECTION
func is_in_water_now() -> bool:
var feet_pos: Vector2 = feet.global_position
for layer in ground_layers:
var tile_pos: Vector2i = layer.local_to_map(feet_pos)
if layer.get_cell_tile_data(tile_pos) != null:
return false
for layer in water_layers:
var tile_pos: Vector2i = layer.local_to_map(feet_pos)
if layer.get_cell_tile_data(tile_pos) != null:
return true
return false
#
# 8 DIRECTION SNAP FOR DASHING
func snap_to_8_dir(vec: Vector2) -> Vector2:
if vec == Vector2.ZERO:
return Vector2.DOWN
var angle: float = vec.angle()
var snapped_angle: float = round(angle / (PI / 4.0)) * (PI / 4.0)
return Vector2.RIGHT.rotated(snapped_angle).normalized()
func _ready() -> void:
last_feet_pos = feet.global_position
in_water = is_in_water_now()
state = State.SWIMMING if in_water else State.NORMAL
func _is_airborne() -> bool:
return state == State.JUMPING or state == State.DASHING
# MAIN LOOP
func _physics_process(delta: float) -> void:
var direction: Vector2 = Input.get_vector("left", "right", "up", "down").normalized()
var grounded: bool = not _is_airborne() and body.position.y >= 0.0
# Event base water update
var current_feet_pos := feet.global_position
if current_feet_pos != last_feet_pos:
in_water = is_in_water_now()
last_feet_pos = current_feet_pos
# State sync with water when on ground
if not _is_airborne():
state = State.SWIMMING if in_water else State.NORMAL
# Coyote time
if grounded:
coyote_timer = COYOTE_TIME
else:
coyote_timer = max(coyote_timer - delta, 0.0)
# Dash cooldown
if dash_cooldown_timer > 0.0:
dash_cooldown_timer = max(dash_cooldown_timer - delta, 0.0)
# Jump
if Input.is_action_just_pressed("jump") and coyote_timer > 0.0:
state = State.JUMPING
can_dash = true
jump_velocity = JUMP_FORCE
coyote_timer = 0.0
object_hitbox.disabled = true
# Dash
if _is_airborne() \
and Input.is_action_just_pressed("leftclick") \
and can_dash \
and dash_cooldown_timer <= 0.0:
state = State.DASHING
can_dash = false
dash_cooldown_timer = DASH_COOLDOWN
dash_timer = DASH_DURATION
object_hitbox.disabled = true
var mouse_dir: Vector2 = global_position.direction_to(get_global_mouse_position())
var snapped_dir: Vector2 = snap_to_8_dir(facing_direction)
var final_dash_dir: Vector2 = snapped_dir.lerp(mouse_dir, 0.5).normalized()
dash_velocity = final_dash_dir * DASH_SPEED
# Dash update
if state == State.DASHING:
dash_timer -= delta
if dash_timer <= 0.0:
state = State.JUMPING # back to normal airborne after dash
# 2d Z-axis jump
if _is_airborne():
body.position.y += jump_velocity * delta
head.position.y = body.position.y
mask.position.y = body.position.y
particles.position.y = body.position.y
jump_velocity += GRAVITY * delta
if body.position.y >= 0.0:
body.position.y = 0.0
head.position.y = 0.0
mask.position.y = 0.0
particles.position.y = 0.0
state = State.SWIMMING if in_water else State.NORMAL
can_dash = true
object_hitbox.disabled = false
if particles.sprite_frames.has_animation("land"):
particles.play("land")
# Movement
if state == State.DASHING:
velocity = dash_velocity
else:
var current_speed = SWIM_SPEED if in_water else SPEED
velocity = direction * current_speed
# Shadow
shadow.visible = _is_airborne() or not in_water
# Animation
_play_animation(direction)
move_and_slide()
# LAYERED ANIMATION SYSTEM
func _play_animation(direction: Vector2) -> void:
var anim := ""
# Jump + Dash
if _is_airborne():
if abs(facing_direction.x) < 0.2:
anim = "jumpup" if facing_direction.y < 0.0 else "jumpdown"
else:
anim = "jumpsideup" if facing_direction.y < 0.0 else "jumpsidedown"
play_all(anim, direction)
return
# Update facing direction
if direction != Vector2.ZERO:
facing_direction = direction
# Swimming
if in_water:
if direction == Vector2.ZERO:
anim = "swimidleup" if facing_direction.y < 0.0 else "swimidledown"
else:
if abs(direction.x) > abs(direction.y):
anim = "swimwalksideup" if direction.y < 0.0 else "swimwalksidedown"
else:
anim = "swimwalkup" if direction.y < 0.0 else "swimwalkdown"
play_all(anim, direction)
return
# Land movement
if direction == Vector2.ZERO:
anim = "idleup" if facing_direction.y < 0.0 else "idledown"
else:
if abs(direction.x) > abs(direction.y):
anim = "walksideup" if direction.y < 0.0 else "walksidedown"
else:
anim = "walkup" if direction.y < 0.0 else "walkdown"
play_all(anim, direction)
func play_all(anim: String, direction: Vector2) -> void:
body.play(anim)
head.play(anim)
mask.play(anim)
if particles.sprite_frames.has_animation(anim):
particles.play(anim)
else:
particles.stop()
var flip_dir := direction
if flip_dir == Vector2.ZERO:
flip_dir = facing_direction
var flip := flip_dir.x < 0.0
body.flip_h = flip
head.flip_h = flip
mask.flip_h = flip
particles.flip_h = flip
i love all your feedback and would love to also give others feedback to!