La-Torreta-del-Drac/scenes/window/dragon.gd
2025-04-10 22:52:28 +02:00

180 lines
4.2 KiB
GDScript

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 id: int
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)
current_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_IDLE:
if not _thinking_path:
_think_path()
State.FLYING_IDLE:
if not _thinking_path:
_think_path()
State.WALKING:
_move_to_target(delta)
State.FALLING:
_fall(delta)
State.FLYING:
_move_to_target(delta)
func dress(hat: Texture2D, shirt: Texture2D, shoes: Texture2D):
dragon.dress(hat, shirt, shoes)
func _think_path():
_thinking_path = true
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
current_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:
current_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:
current_state = State.FLYING_IDLE
State.WALKING:
current_state = State.WALKING_IDLE
func _on_drag():
current_state = State.DRAGGING
func _on_drop():
var ground_height: int = _ground_height()
if position.y >= ground_height:
current_state = State.WALKING_IDLE
position.y = ground_height
_actual_position.y = ground_height
else:
_fall_speed = 0
current_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:
current_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:
current_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