175 lines
5.0 KiB
GDScript
175 lines
5.0 KiB
GDScript
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 {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 input_buffer: StringName = ""
|
|
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
|
|
|
|
# Buffer inputs
|
|
if Input.is_action_just_pressed(&"jump"):
|
|
input_buffer = &"jump"
|
|
|
|
if Input.is_action_just_pressed(&"roll"):
|
|
input_buffer = &"roll"
|
|
|
|
if Input.is_action_just_pressed(&"roll_jump"):
|
|
input_buffer = &"roll_jump"
|
|
|
|
if Input.is_action_just_pressed(&"melee"):
|
|
input_buffer = &"melee"
|
|
|
|
# Jumping
|
|
if state not in STATES_IMMOBILE and state not in STATES_AIRBORNE and input_buffer == "jump" and Input.is_action_pressed("jump") and is_on_floor():
|
|
state = States.JUMP_START
|
|
input_buffer = ""
|
|
|
|
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 /= 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_buffer in ["roll", "roll_jump"] and \
|
|
(Input.is_action_pressed("roll_jump") or (Input.is_action_pressed("roll") and direction)):
|
|
state = States.ROLL
|
|
input_buffer = ""
|
|
|
|
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_pressed("roll_jump"):
|
|
velocity.y = -120
|
|
|
|
# Melee
|
|
if state not in STATES_IMMOBILE and input_buffer == "melee" and Input.is_action_pressed("melee"):
|
|
input_buffer = ""
|
|
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()
|