capri/objects/player/player.gd

135 lines
3.2 KiB
GDScript

class_name Player
extends CharacterBody2D
@export_group("Ground Movement")
@export var run_acceleration: float
@export var max_run_speed: float
@export var turn_acceleration: float
@export var stopping_force: float
@export_group("Air Movement")
@export var gravity: float
@export var jump_power: float
@export var splat_launch_power: float
@export var splat_offset: float
@export_group("Internal References")
@export var state_chart: StateChart
@export var graphics: Node2D
@export var run_animation: SpritesheetAnimation
@onready var start_position: Vector2 = global_position
var input_dir: Vector2 = Vector2.ZERO:
set(value):
input_dir = value.sign()
state_chart.set_expression_property(&"input_dir", input_dir)
var _last_velocity: Vector2 = Vector2.ZERO
var _splat_normal: Vector2 = Vector2.ZERO
func _physics_process(delta: float) -> void:
_last_velocity = velocity
move_and_slide()
state_chart.set_expression_property(&"velocity", velocity)
if velocity.x != 0.0:
graphics.scale.x = signf(velocity.x)
state_chart.set_expression_property(&"on_floor", is_on_floor())
input_dir = Input.get_vector(&"move_left", &"move_right", &"move_up", &"move_down")
state_chart.send_event(&"tick")
func _unhandled_input(event: InputEvent) -> void:
if event.is_action_pressed(&"jump"):
state_chart.send_event(&"jump_pressed")
func kill() -> void:
state_chart.send_event(&"killed")
func launch(impulse: Vector2) -> void:
velocity = impulse
state_chart.send_event(&"launched")
#region Idle
func _slow_to_stop(delta: float) -> void:
velocity.x = move_toward(velocity.x, 0.0, stopping_force * delta)
#endregion
#region Running
func _apply_run_acceleration(delta: float) -> void:
if absf(velocity.x) < max_run_speed:
velocity.x += input_dir.x * run_acceleration * delta
func _scale_run_animation(delta:float) -> void:
run_animation.speed_scale = inverse_lerp(0.0, max_run_speed, absf(velocity.x))
#endregion
#region Turning
func _apply_turn_acceleration(delta: float) -> void:
velocity.x += input_dir.x * turn_acceleration * delta
#endregion
#region Falling
func _apply_gravity(delta: float) -> void:
velocity.y += gravity * delta
#endregion
#region Jumping
func _start_jump() -> void:
velocity.y = -jump_power
#endregion
#region Missile
func _restore_graphics_rotation() -> void:
graphics.rotation = 0.0
func _face_towards_velocity(_delta: float) -> void:
graphics.rotation = Vector2(graphics.scale.x, 0.0).angle_to(velocity)
func _check_for_splat(delta: float) -> void:
var col = move_and_collide(_last_velocity * delta, true)
if col:
velocity = Vector2.ZERO
global_position += col.get_travel()
_splat_normal = col.get_normal()
var angle = col.get_normal().angle()
if graphics.scale.x > 0.0:
angle += PI
graphics.set_deferred(&"rotation", angle)
state_chart.send_event(&"splatted")
#endregion
#region Splatting
func _do_splat_launch() -> void:
var dir = input_dir.project(_splat_normal.orthogonal()).normalized()
if dir == Vector2.ZERO:
dir = _splat_normal
dir = dir.rotated(dir.angle_to(_splat_normal) * 0.5)
launch(dir * splat_launch_power)
#endregion
#region Death
func _reset_position() -> void:
global_position = start_position
velocity = Vector2.ZERO
graphics.scale.x = 1.0
graphics.rotation = 0.0
#endregion