This repository has been archived on 2024-09-30. You can view files and clone it, but cannot push or open issues/pull-requests.
gbjam12/entities/player/player.gd

184 lines
4.6 KiB
GDScript

class_name Player
extends CharacterBody2D
@onready var death_sfx = preload("res://scenes/assets/jingles/fail.wav")
@onready var raycast: RayCast2D = $RayCast2D
@onready var sprite: AnimatedSprite2D = $AnimatedSprite2D
@onready var animation_player: AnimationPlayer = $AnimationPlayer
@onready var map: MainLevel = get_tree().root.get_child(0).get_node("TileMap")
@onready var tile_map: TileMapLayer = get_tree().root.get_child(0).get_node("TileMap/TileMapLayer")
@onready var camera: Camera2D = $AnimatedSprite2D/Camera2D
@onready var audio_player: AudioStreamPlayer2D = $AudioStreamPlayer2D
@onready var start_point: Node2D = get_tree().root.get_child(0).get_node("Start")
const TILE_SIZE = 8
@export var speed: float = 40
@export var checkpoints: Array[Node2D]
@export var current_checkpoint := 0
var is_moving = false
var should_move = false
var is_dead = false
var input_dir: Vector2
var respawn_time: int = 10
var can_teleport := true
var rng := RandomNumberGenerator.new()
var camera_shake: float = 0.0
var camera_shake_fade: float = 0.0
var attack_frame := 0
var lock_for_end := false
var end_tick := 0
func _ready():
_respawn()
pass
func _process(delta):
if not is_dead:
_try_get_input()
_try_interact()
_shake_camera(delta)
if is_dead:
if respawn_time > 0:
respawn_time -= 1
elif respawn_time <= 0:
_respawn()
func _physics_process(delta):
_try_move(delta)
func _respawn():
sprite.stop()
sprite.frame = 0
if checkpoints.size() > 0 and checkpoints[current_checkpoint]:
position = checkpoints[current_checkpoint].position
else:
position = start_point.position
sprite.global_position = position
is_dead = false
is_moving = false
should_move = false
func _try_get_input():
should_move = false
if not lock_for_end:
if Input.is_action_pressed("move_up"):
input_dir = Vector2.UP
should_move = true
elif Input.is_action_pressed("move_right"):
input_dir = Vector2.RIGHT
should_move = true
elif Input.is_action_pressed("move_down"):
input_dir = Vector2.DOWN
should_move = true
elif Input.is_action_pressed("move_left"):
input_dir = Vector2.LEFT
should_move = true
else:
input_dir = Vector2.UP
should_move = true
end_tick += 1
if end_tick > 250:
animation_player.play(&"end")
_change_sprite()
if attack_frame > 0:
attack_frame -= 1
if not should_move and not is_moving and attack_frame <= 0:
sprite.frame = 0
sprite.stop()
if should_move and not is_moving:
sprite.play()
raycast.target_position = input_dir * 8
raycast.force_raycast_update()
if raycast.is_colliding():
return
var current_tile: Vector2i = tile_map.local_to_map(global_position)
var target_tile: Vector2i = Vector2i(
current_tile.x + input_dir.x,
current_tile.y + input_dir.y
)
global_position = tile_map.map_to_local(target_tile)
var is_death_tile = map.is_death_tile(global_position)
if is_death_tile:
die()
return
is_moving = true
sprite.global_position = tile_map.map_to_local(current_tile)
func _change_sprite():
var is_attacking = attack_frame > 0
if not is_attacking:
if input_dir == Vector2.UP:
sprite.animation = &"move_up"
elif input_dir == Vector2.RIGHT:
sprite.animation = &"move_right"
sprite.flip_h = false
elif input_dir == Vector2.DOWN:
sprite.animation = &"move_down"
elif input_dir == Vector2.LEFT:
sprite.animation = &"move_right"
sprite.flip_h = true
func _try_move(delta: int):
if not is_moving or is_dead:
return
sprite.global_position = sprite.global_position.move_toward(global_position, 0.5)
if global_position == sprite.global_position:
is_moving = false
return
func die():
is_dead = true
is_moving = false
respawn_time = 10
audio_player.stream = death_sfx
audio_player.play()
func apply_camera_shake(strength: float = 10.0, fade: float = 5.0):
camera_shake = strength
camera_shake_fade = fade
func _try_interact():
if lock_for_end:
return
raycast.target_position = input_dir * 8
raycast.force_raycast_update()
if Input.is_action_just_pressed("attack"):
sprite.play(&"spin")
attack_frame = 50
var collider = raycast.get_collider()
if collider and collider is PuzzleElement:
(collider as PuzzleElement).interact(self)
func teleport(pos: Vector2i):
global_position = pos
can_teleport = false
func _shake_camera(delta):
if camera_shake > 0:
camera_shake = lerpf(camera_shake, 0, camera_shake_fade * delta)
camera.offset = Vector2(rng.randf_range(-camera_shake, camera_shake), rng.randf_range(-camera_shake, camera_shake))
func _on_area_entered(area: Area2D):
if area.is_in_group("death"):
die()
func _on_animation_player_animation_finished(anim_name: String):
if anim_name == &"end":
get_tree().quit()