keebie/scripts/player.gd

112 lines
2.6 KiB
GDScript

class_name Player extends Node3D
#region variables
@export_group("References")
@export var _keyboard: GameKeyboard
@export_group("Animation")
@export_subgroup("Moving")
@export var _move_duration: float = 0.1
@export var _move_hop_height: float = 1
var _current_key: GameKey
var _starting_keycode: Key = KEY_H
var _rotation: Quaternion
var _move_timer: float
var _is_moving: bool
var _prev_pos: Vector3
#endregion
#region builtins
func _ready() -> void:
_keyboard.key_press_changed.connect(_on_keyboard_key_press_changed)
_current_key = _keyboard.request_key_by_keycode(_starting_keycode)
if _current_key:
global_transform = _current_key.player_pos_marker.global_transform
_keyboard.emit_player_key_change(_current_key)
func _process(delta: float) -> void:
_animate(delta)
#endregion
#region movement
func _move(game_key: GameKey) -> void:
var look_from := _current_key.player_pos_marker.transform * _current_key.transform
var look_target := game_key.player_pos_marker.transform * game_key.transform
look_target.origin.y = look_from.origin.y
var looking := look_from.looking_at(look_target.origin, Vector3.UP, true)
_rotation = (looking.basis.get_rotation_quaternion())
_prev_pos = _current_key.player_pos_marker.global_position
_move_timer = _move_duration
if _is_moving:
_finish_move(true)
_is_moving = true
_current_key = game_key
_keyboard.emit_player_key_change(game_key)
#endregion
#region animation
func _animate(delta: float) -> void:
if not _current_key:
return
if _move_timer <= 0:
if _is_moving:
_is_moving = false
_finish_move(false)
global_position = _animate_position()
else:
_move_timer -= delta
var lerp_value := 1 - (_move_timer / _move_duration)
global_position = lerp(_prev_pos, _animate_position(), lerp_value)
var hop_value := 1 - absf(lerp_value * 2 - 1)
hop_value = 1 - pow(1 - hop_value, 3)
global_position.y += hop_value * _move_hop_height
global_rotation = _animate_rotation()
func _animate_position() -> Vector3:
return _current_key.player_pos_marker.global_position
func _animate_rotation() -> Vector3:
var rotation_translate := (
_current_key.get_default_transform().inverse()
* _current_key.player_pos_marker.global_transform
)
return (
(_rotation * (rotation_translate.basis.get_rotation_quaternion())).get_euler()
)
func _finish_move(_interrupted: bool) -> void:
_keyboard.emit_player_finished_move(_current_key)
#endregion
#region event handlers
func _on_keyboard_key_press_changed(game_key: GameKey, event: InputEventKey) -> void:
if (
event.is_pressed()
and _current_key
and KeyAdjacency.is_adjacent(_current_key, game_key)
):
_move(game_key)
#endregion