class_name Player extends CharacterBody2D @onready var raycast: RayCast2D = $RayCast2D @onready var sprite: Sprite2D = $Sprite2D @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 = $Sprite2D/Camera2D @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 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(): 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 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 if should_move and not is_moving: 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 _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 func apply_camera_shake(strength: float = 10.0, fade: float = 5.0): camera_shake = strength camera_shake_fade = fade func _try_interact(): raycast.target_position = input_dir * 8 raycast.force_raycast_update() var collider = raycast.get_collider() if Input.is_action_just_pressed("attack") and collider: if collider is PuzzleElement: (collider as PuzzleElement).interact(self) pass pass 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()