extends Window class_name Dragon @export var dragon_speed_min: float = 20.0 @export var dragon_speed_max: float = 20.0 var dragon_speed: float = 0.0 @export var dragon: DragonSprite @onready var _actual_position: Vector2 = position var main_window_rect: Rect2i @export var draggable: Draggable var _thinking_path: bool = false var _target_pos: Vector2 var rng: RandomNumberGenerator = RandomNumberGenerator.new() var _fall_speed: float signal place_back(dragon: Dragon) var properties: DragonProperties enum State { WALKING_IDLE, WALKING, FLYING, FLYING_IDLE, FALLING, DRAGGING } var current_state: State = State.WALKING_IDLE func _ready() -> void: draggable.on_drag.connect(_on_drag) draggable.on_drop.connect(_on_drop) _change_state(State.FALLING) func on_place_back() -> void: place_back.emit(self) func start_dragon_drag()-> void: draggable.queue_initial_drag() func _process(delta: float) -> void: match current_state: State.DRAGGING: _thinking_path = false _actual_position = position State.WALKING: _move_to_target(delta) State.FALLING: _fall(delta) State.FLYING: _move_to_target(delta) properties.position = position func _change_state(new_state): match new_state: State.DRAGGING: dragon.play_idle() State.WALKING_IDLE: dragon.play_idle() _think_path() State.FLYING_IDLE: _think_path() State.WALKING: dragon.play_walk() State.FALLING: dragon.play_idle() State.FLYING: dragon.play_fly() current_state = new_state func dress(): dragon.dress(properties) func _think_path(): await get_tree().create_timer(rng.randf_range(2, 7)).timeout dragon_speed = rng.randf_range(dragon_speed_min, dragon_speed_max) match current_state: State.WALKING_IDLE: var decision: int = rng.randi_range(0, 99) if decision < 30: _pick_random_screen_fly_position() else: _pick_random_screen_walk_position() State.FLYING_IDLE: var decision: int = rng.randi_range(0, 99) if decision < 30: _fall_speed = 0 _change_state(State.FALLING) else: _pick_random_screen_fly_position() func _fall(delta: float) -> void: _fall_speed += 30 * delta _actual_position.y += _fall_speed position.y = _actual_position.y var ground_height: int = _ground_height() if position.y >= ground_height: _change_state(State.WALKING_IDLE) position.y = ground_height _actual_position.y = ground_height func _move_to_target(delta: float): if _actual_position.distance_to(_target_pos) > 2.0: var direction: Vector2 = (_target_pos - _actual_position).normalized() _actual_position += dragon_speed * direction * delta position = _actual_position if direction.x > 0: dragon.walk_right() elif direction.x < 0: dragon.walk_left() return match current_state: State.FLYING: _change_state(State.FLYING_IDLE) State.WALKING: _change_state(State.WALKING_IDLE) func _on_drag(): _change_state(State.DRAGGING) func _on_drop(): var ground_height: int = _ground_height() if position.y >= ground_height: _change_state(State.WALKING_IDLE) position.y = ground_height _actual_position.y = ground_height else: _fall_speed = 0 _change_state(State.FALLING) func _get_display_limits() -> Rect2i: var display_index: int = DisplayServer.window_get_current_screen() var work_area_position: Vector2i = DisplayServer.screen_get_usable_rect(display_index).position var work_area_size: Vector2i = DisplayServer.screen_get_usable_rect(display_index).size return Rect2i(work_area_position + Vector2i(10, 10), work_area_size - Vector2i(20, 10) - size) func _ground_height() -> int: var limits: Rect2i = _get_display_limits() return limits.end.y func _pick_random_screen_fly_position() -> void: _change_state(State.FLYING) _thinking_path = false var limits: Rect2i = _get_display_limits() var random_pos: Vector2i = Vector2i( rng.randi_range(limits.position.x, limits.end.x), rng.randi_range(limits.position.y, limits.end.y) ) _target_pos = random_pos func _pick_random_screen_walk_position() -> void: _change_state(State.WALKING) _thinking_path = false var limits: Rect2i = _get_display_limits() var random_pos: Vector2i = Vector2i( rng.randi_range(limits.position.x, limits.end.x), _ground_height() ) _target_pos = random_pos func get_taskbar_height(): return DisplayServer.screen_get_size().y - DisplayServer.screen_get_usable_rect().size.y