180 lines
4.2 KiB
GDScript
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
|