class_name Player extends CharacterBody2D @onready var sprite := $Sprite as AnimatedSprite2D @onready var audio_player := $AudioPlayer as AudioStreamPlayer signal state_change(old: States, new: States) enum States {NULL, IDLE, RUN_START, RUN, ROLL, JUMP_START, JUMP, FALL, LAND, DAMAGE, RAGDOLL, BOUNCE, LAY, SHOOT, JAB, STRAIGHT, KICK, POUND, POUND_FALL} const STATES_IMMOBILE = [States.ROLL, States.DAMAGE, States.RAGDOLL, States.BOUNCE, States.LAY, States.SHOOT, States.JAB, States.STRAIGHT, States.KICK, States.POUND, States.POUND_FALL] const STATES_MOVEMENT = [States.RUN_START, States.RUN, States.JUMP_START, States.JUMP, States.FALL] const STATES_ATTACK = [States.JAB, States.STRAIGHT, States.KICK, States.POUND] const STATES_AIRBORNE = [States.JUMP_START, States.JUMP, States.FALL] # FX const ROLL_DUST = preload("uid://botc600n5fcgt") const JUMP_DUST = preload("uid://c4h1cj75b5sry") # Sounds const JUMP_SOUND = preload("uid://d1hwunwdel6sy") const HIT_GROUND = preload("uid://ciglwfq0vua8i") const POUND_SOUND = preload("uid://css0nv2dxb52w") # Projectiles const POUND_BULLET = preload("uid://5uiinhmeyov0") const SPEED = 90.0 const ACCEL = 450 const JUMP_VELOCITY = -312.0 const ROLL_VELOCITY = 150.0 const ROLL_DECEL = 1080 var state: States = States.IDLE: set = _set_state var state_buffer: States = States.NULL var direction: float func _set_state(s: States): state_change.emit(state, s) state = s func _process(_delta: float) -> void: $State.text = States.keys()[state] func _physics_process(delta): # Add the gravity. if not is_on_floor(): velocity += get_gravity() * delta # Jumping if state not in STATES_IMMOBILE and state not in STATES_AIRBORNE and Input.is_action_just_pressed("jump") and is_on_floor(): state = States.JUMP_START audio_player.stream = JUMP_SOUND audio_player.play() var jump_dust = JUMP_DUST.instantiate() jump_dust.position = position add_sibling(jump_dust) velocity.y = JUMP_VELOCITY # Short hops if state in [States.JUMP_START, States.JUMP] and Input.is_action_just_released("jump") and !is_on_floor(): velocity.y = velocity.y / 2 # Falling if state in [States.IDLE] + STATES_MOVEMENT and velocity.y > 0: state = States.FALL # Landing if state in [States.FALL] and is_on_floor(): if direction: state = States.RUN else: state = States.LAND # Rolls if state not in STATES_IMMOBILE and state != States.ROLL and \ (Input.is_action_just_pressed("roll_jump") or (Input.is_action_just_pressed("roll") and direction)): state = States.ROLL if is_on_floor(): var roll_dust = ROLL_DUST.instantiate() roll_dust.position = position roll_dust.flip_h = !sprite.flip_h add_sibling(roll_dust) if !sprite.flip_h: velocity.x = ROLL_VELOCITY else: velocity.x = -ROLL_VELOCITY if velocity.y >= 0 && Input.is_action_just_pressed("roll_jump"): velocity.y = -120 # Melee if state not in STATES_IMMOBILE and Input.is_action_just_pressed("melee"): if Input.is_action_pressed("roll"): state = States.POUND velocity.x = 0 elif state in STATES_AIRBORNE: state = States.KICK else: state = States.JAB # Pound if state in [States.POUND_FALL] and is_on_floor(): state = States.POUND # Shooting #if state not in STATES_IMMOBILE and Input.is_action_just_pressed("shoot"): #state = States.SHOOT #match global.save.projectile: #global.save.Projectile.BLAST: #pass # Ragdoll if state not in [States.RAGDOLL, States.BOUNCE, States.LAY] and Input.is_action_just_pressed("ragdoll"): state = States.RAGDOLL if state in [States.RAGDOLL] and is_on_floor(): state = States.BOUNCE var roll_dust = ROLL_DUST.instantiate() roll_dust.position = position roll_dust.flip_h = !sprite.flip_h add_sibling(roll_dust) velocity.y = -120 audio_player.stream = HIT_GROUND audio_player.play() if state in [States.BOUNCE] and is_on_floor() and velocity.y >= 0: state = States.LAY audio_player.stream = HIT_GROUND audio_player.play() if state in [States.LAY] and is_on_floor(): velocity.x = move_toward(velocity.x, 0, ACCEL * delta) # Overall physics direction = Input.get_axis("move_left", "move_right") if state == States.ROLL and sprite.frame > 7: # Slow down if in the later roll frames. velocity.x = move_toward(velocity.x, 0, ROLL_DECEL * delta) elif state not in STATES_IMMOBILE: # Apply velocity changes if not in a restricted movement state. velocity.x = move_toward(velocity.x, direction * SPEED, ACCEL * delta) if direction: if state not in STATES_MOVEMENT: state = States.RUN_START else: if state not in (STATES_AIRBORNE + [States.LAND]): state = States.IDLE move_and_slide()