feat: improved dragon walking behaviour
This commit is contained in:
parent
b4594bdd43
commit
d8419cb9a4
8 changed files with 150 additions and 66 deletions
|
@ -8,7 +8,7 @@ class_name DragonEntity
|
||||||
@export var min_exit_time: float
|
@export var min_exit_time: float
|
||||||
@export var max_exit_time: float
|
@export var max_exit_time: float
|
||||||
|
|
||||||
signal on_pick(dragon_id: int, position: Vector2, hat: Texture2D, shirt: Texture2D, shoes: Texture2D, dragon_name: String)
|
signal on_pick(dragon_id: int, position: Vector2, hat: Texture2D, shirt: Texture2D, shoes: Texture2D)
|
||||||
signal on_quit(dragon_id: int)
|
signal on_quit(dragon_id: int)
|
||||||
|
|
||||||
var rng: RandomNumberGenerator = RandomNumberGenerator.new()
|
var rng: RandomNumberGenerator = RandomNumberGenerator.new()
|
||||||
|
@ -43,13 +43,9 @@ func _input_event(viewport, event, shape_idx) -> void:
|
||||||
if event is InputEventMouseButton \
|
if event is InputEventMouseButton \
|
||||||
and event.button_index == MOUSE_BUTTON_LEFT \
|
and event.button_index == MOUSE_BUTTON_LEFT \
|
||||||
and event.is_pressed():
|
and event.is_pressed():
|
||||||
on_pick.emit(id, position + $CollisionShape2D.position, dragon.hat.texture, dragon.shirt.texture, dragon.shoes.texture, dragon.name_label.text)
|
on_pick.emit(id, position + $CollisionShape2D.position, dragon.hat.texture, dragon.shirt.texture, dragon.shoes.texture)
|
||||||
queue_free()
|
queue_free()
|
||||||
|
|
||||||
|
|
||||||
func dress(hat: Texture2D, shirt: Texture2D, shoes: Texture2D):
|
func dress(hat: Texture2D, shirt: Texture2D, shoes: Texture2D):
|
||||||
dragon.dress(hat, shirt, shoes)
|
dragon.dress(hat, shirt, shoes)
|
||||||
|
|
||||||
|
|
||||||
func set_dragon_name(dragon_name: String):
|
|
||||||
dragon.set_dragon_name(dragon_name)
|
|
||||||
|
|
|
@ -5,11 +5,6 @@ class_name DragonSprite
|
||||||
@export var hat: Sprite2D
|
@export var hat: Sprite2D
|
||||||
@export var shirt: Sprite2D
|
@export var shirt: Sprite2D
|
||||||
@export var shoes: Sprite2D
|
@export var shoes: Sprite2D
|
||||||
@export var name_label: Label
|
|
||||||
|
|
||||||
|
|
||||||
func _ready() -> void:
|
|
||||||
name_label.hide()
|
|
||||||
|
|
||||||
|
|
||||||
func dress(hat: Texture2D, shirt: Texture2D, shoes: Texture2D):
|
func dress(hat: Texture2D, shirt: Texture2D, shoes: Texture2D):
|
||||||
|
@ -18,13 +13,9 @@ func dress(hat: Texture2D, shirt: Texture2D, shoes: Texture2D):
|
||||||
self.shoes.texture = shoes
|
self.shoes.texture = shoes
|
||||||
|
|
||||||
|
|
||||||
func set_dragon_name(dragon_name: String):
|
func walk_left():
|
||||||
name_label.text = dragon_name
|
$Sprite.scale.x = 1
|
||||||
|
|
||||||
|
|
||||||
func _on_area_2d_mouse_entered() -> void:
|
func walk_right():
|
||||||
name_label.show()
|
$Sprite.scale.x = -1
|
||||||
|
|
||||||
|
|
||||||
func _on_area_2d_mouse_exited() -> void:
|
|
||||||
name_label.hide()
|
|
||||||
|
|
|
@ -9,12 +9,11 @@
|
||||||
[sub_resource type="RectangleShape2D" id="RectangleShape2D_oaoux"]
|
[sub_resource type="RectangleShape2D" id="RectangleShape2D_oaoux"]
|
||||||
size = Vector2(76, 88)
|
size = Vector2(76, 88)
|
||||||
|
|
||||||
[node name="Dragon" type="Node2D" node_paths=PackedStringArray("hat", "shirt", "shoes", "name_label")]
|
[node name="Dragon" type="Node2D" node_paths=PackedStringArray("hat", "shirt", "shoes")]
|
||||||
script = ExtResource("1_oaoux")
|
script = ExtResource("1_oaoux")
|
||||||
hat = NodePath("Sprite/Hat")
|
hat = NodePath("Sprite/Hat")
|
||||||
shirt = NodePath("Sprite/Shirt")
|
shirt = NodePath("Sprite/Shirt")
|
||||||
shoes = NodePath("Sprite/Shoes")
|
shoes = NodePath("Sprite/Shoes")
|
||||||
name_label = NodePath("Label")
|
|
||||||
|
|
||||||
[node name="Area2D" type="Area2D" parent="."]
|
[node name="Area2D" type="Area2D" parent="."]
|
||||||
|
|
||||||
|
@ -35,16 +34,5 @@ texture = ExtResource("4_oaoux")
|
||||||
[node name="Shoes" type="Sprite2D" parent="Sprite"]
|
[node name="Shoes" type="Sprite2D" parent="Sprite"]
|
||||||
texture = ExtResource("5_stf6f")
|
texture = ExtResource("5_stf6f")
|
||||||
|
|
||||||
[node name="Label" type="Label" parent="."]
|
|
||||||
offset_left = -10.0
|
|
||||||
offset_top = 78.0
|
|
||||||
offset_right = 86.0
|
|
||||||
offset_bottom = 101.0
|
|
||||||
theme_override_colors/font_color = Color(1, 1, 1, 1)
|
|
||||||
theme_override_colors/font_outline_color = Color(0, 0, 0, 1)
|
|
||||||
theme_override_constants/outline_size = 5
|
|
||||||
text = "AAAAAAAA"
|
|
||||||
horizontal_alignment = 1
|
|
||||||
|
|
||||||
[connection signal="mouse_entered" from="Area2D" to="." method="_on_area_2d_mouse_entered"]
|
[connection signal="mouse_entered" from="Area2D" to="." method="_on_area_2d_mouse_entered"]
|
||||||
[connection signal="mouse_exited" from="Area2D" to="." method="_on_area_2d_mouse_exited"]
|
[connection signal="mouse_exited" from="Area2D" to="." method="_on_area_2d_mouse_exited"]
|
||||||
|
|
|
@ -101,14 +101,13 @@ func _load_game():
|
||||||
var hat: Texture2D = hat_outfits.get_texture(d['hat'])
|
var hat: Texture2D = hat_outfits.get_texture(d['hat'])
|
||||||
var shirt: Texture2D = shirt_outfits.get_texture(d['shirt'])
|
var shirt: Texture2D = shirt_outfits.get_texture(d['shirt'])
|
||||||
var shoes: Texture2D = shoes_outfits.get_texture(d['shoes'])
|
var shoes: Texture2D = shoes_outfits.get_texture(d['shoes'])
|
||||||
_pick_dragon(d['id'], d['pos'], hat, shirt, shoes, d['name'], false)
|
_pick_dragon(d['id'], d['pos'], hat, shirt, shoes, false)
|
||||||
print(_save_load.contents_to_save)
|
print(_save_load.contents_to_save)
|
||||||
|
|
||||||
|
|
||||||
func _instantiate_dragon_ingame(position: Vector2, hat: Texture2D, shirt: Texture2D, shoes: Texture2D, dragon_name: String, id: int) -> DragonEntity:
|
func _instantiate_dragon_ingame(position: Vector2, hat: Texture2D, shirt: Texture2D, shoes: Texture2D, dragon_name: String, id: int) -> DragonEntity:
|
||||||
var dragon: DragonEntity = dragon_ingame.instantiate()
|
var dragon: DragonEntity = dragon_ingame.instantiate()
|
||||||
dragon.dress(hat, shirt, shoes)
|
dragon.dress(hat, shirt, shoes)
|
||||||
dragon.set_dragon_name(dragon_name)
|
|
||||||
add_child(dragon)
|
add_child(dragon)
|
||||||
dragon.id = id
|
dragon.id = id
|
||||||
dragon.position = position
|
dragon.position = position
|
||||||
|
@ -118,8 +117,8 @@ func _instantiate_dragon_ingame(position: Vector2, hat: Texture2D, shirt: Textur
|
||||||
return dragon
|
return dragon
|
||||||
|
|
||||||
|
|
||||||
func _pick_dragon(id: int, position: Vector2, hat: Texture2D, shirt: Texture2D, shoes: Texture2D, dragon_name: String, drag: bool = true):
|
func _pick_dragon(id: int, position: Vector2, hat: Texture2D, shirt: Texture2D, shoes: Texture2D, drag: bool = true):
|
||||||
var dragon: Dragon = _instantiator.instantiate(position, hat, shirt, shoes, dragon_name, drag)
|
var dragon: Dragon = _instantiator.instantiate(position, hat, shirt, shoes, drag)
|
||||||
dragon.id = id
|
dragon.id = id
|
||||||
_dragon_entities[id] = dragon
|
_dragon_entities[id] = dragon
|
||||||
dragon.place_back.connect(_dragon_place_back)
|
dragon.place_back.connect(_dragon_place_back)
|
||||||
|
|
|
@ -9,6 +9,9 @@ var dragging_start_position: Vector2i = Vector2i()
|
||||||
|
|
||||||
var _initial_drag_requested: bool = false
|
var _initial_drag_requested: bool = false
|
||||||
|
|
||||||
|
signal on_drag()
|
||||||
|
signal on_drop()
|
||||||
|
|
||||||
|
|
||||||
func _ready() -> void:
|
func _ready() -> void:
|
||||||
set_process_input(true)
|
set_process_input(true)
|
||||||
|
@ -33,9 +36,11 @@ func _input(event) -> void:
|
||||||
|
|
||||||
if event.pressed:
|
if event.pressed:
|
||||||
dragging = true
|
dragging = true
|
||||||
|
on_drag.emit()
|
||||||
dragging_start_position = Vector2i(get_global_mouse_position())
|
dragging_start_position = Vector2i(get_global_mouse_position())
|
||||||
else:
|
else:
|
||||||
dragging = false
|
dragging = false
|
||||||
|
on_drop.emit()
|
||||||
if _is_inside_main_window():
|
if _is_inside_main_window():
|
||||||
_destroy_dragon()
|
_destroy_dragon()
|
||||||
|
|
||||||
|
|
|
@ -1,23 +1,43 @@
|
||||||
extends Window
|
extends Window
|
||||||
class_name Dragon
|
class_name Dragon
|
||||||
|
|
||||||
@export var dragon_speed: float = 20.0
|
@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
|
@export var dragon: DragonSprite
|
||||||
|
|
||||||
@onready var _actual_position: Vector2 = position
|
@onready var _actual_position: Vector2 = position
|
||||||
var main_window_rect: Rect2i
|
var main_window_rect: Rect2i
|
||||||
@export var draggable: Draggable
|
@export var draggable: Draggable
|
||||||
|
|
||||||
var _walking: bool = false
|
|
||||||
var _thinking_path: bool = false
|
var _thinking_path: bool = false
|
||||||
var _target_pos: Vector2
|
var _target_pos: Vector2
|
||||||
var rng: RandomNumberGenerator = RandomNumberGenerator.new()
|
var rng: RandomNumberGenerator = RandomNumberGenerator.new()
|
||||||
|
var _fall_speed: float
|
||||||
|
|
||||||
signal place_back(dragon: Dragon)
|
signal place_back(dragon: Dragon)
|
||||||
|
|
||||||
var id: int
|
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:
|
func on_place_back() -> void:
|
||||||
place_back.emit(self)
|
place_back.emit(self)
|
||||||
|
|
||||||
|
@ -26,18 +46,21 @@ func start_dragon_drag()-> void:
|
||||||
draggable.queue_initial_drag()
|
draggable.queue_initial_drag()
|
||||||
|
|
||||||
func _process(delta: float) -> void:
|
func _process(delta: float) -> void:
|
||||||
if draggable.dragging:
|
match current_state:
|
||||||
|
State.DRAGGING:
|
||||||
|
_thinking_path = false
|
||||||
_actual_position = position
|
_actual_position = position
|
||||||
_walking = false
|
State.WALKING_IDLE:
|
||||||
return
|
|
||||||
|
|
||||||
if not _walking:
|
|
||||||
if not _thinking_path:
|
if not _thinking_path:
|
||||||
_thinking_path = true
|
_think_path()
|
||||||
await get_tree().create_timer(rng.randf_range(2, 7)).timeout
|
State.FLYING_IDLE:
|
||||||
_pick_random_screen_position()
|
if not _thinking_path:
|
||||||
return
|
_think_path()
|
||||||
|
State.WALKING:
|
||||||
|
_move_to_target(delta)
|
||||||
|
State.FALLING:
|
||||||
|
_fall(delta)
|
||||||
|
State.FLYING:
|
||||||
_move_to_target(delta)
|
_move_to_target(delta)
|
||||||
|
|
||||||
|
|
||||||
|
@ -45,31 +68,113 @@ func dress(hat: Texture2D, shirt: Texture2D, shoes: Texture2D):
|
||||||
dragon.dress(hat, shirt, shoes)
|
dragon.dress(hat, shirt, shoes)
|
||||||
|
|
||||||
|
|
||||||
func set_dragon_name(dragon_name: String):
|
func _think_path():
|
||||||
dragon.set_dragon_name(dragon_name)
|
_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):
|
func _move_to_target(delta: float):
|
||||||
if _actual_position.distance_to(_target_pos) > 10.0:
|
if _actual_position.distance_to(_target_pos) > 2.0:
|
||||||
var direction: Vector2 = (_target_pos - _actual_position).normalized()
|
var direction: Vector2 = (_target_pos - _actual_position).normalized()
|
||||||
_actual_position += dragon_speed * direction * delta
|
_actual_position += dragon_speed * direction * delta
|
||||||
position = _actual_position
|
position = _actual_position
|
||||||
|
|
||||||
|
if direction.x > 0:
|
||||||
|
dragon.walk_right()
|
||||||
|
elif direction.x < 0:
|
||||||
|
dragon.walk_left()
|
||||||
return
|
return
|
||||||
|
|
||||||
_walking = false
|
match current_state:
|
||||||
|
State.FLYING:
|
||||||
|
current_state = State.FLYING_IDLE
|
||||||
|
State.WALKING:
|
||||||
|
current_state = State.WALKING_IDLE
|
||||||
|
|
||||||
|
|
||||||
func _pick_random_screen_position() -> void:
|
func _on_drag():
|
||||||
_walking = true
|
current_state = State.DRAGGING
|
||||||
_thinking_path = false
|
|
||||||
|
|
||||||
|
|
||||||
|
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 display_index: int = DisplayServer.window_get_current_screen()
|
||||||
var work_area_position: Vector2i = DisplayServer.screen_get_usable_rect(display_index).position
|
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
|
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(
|
var random_pos: Vector2i = Vector2i(
|
||||||
work_area_position.x + rng.randi_range(10, work_area_size.x - 10 - size.x),
|
rng.randi_range(limits.position.x, limits.end.x),
|
||||||
work_area_position.y + rng.randi_range(10, work_area_size.y - 10 - size.y)
|
rng.randi_range(limits.position.y, limits.end.y)
|
||||||
)
|
)
|
||||||
|
|
||||||
_target_pos = random_pos
|
_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
|
||||||
|
|
|
@ -13,7 +13,8 @@ borderless = true
|
||||||
transparent = true
|
transparent = true
|
||||||
content_scale_mode = 2
|
content_scale_mode = 2
|
||||||
script = ExtResource("1_ctdir")
|
script = ExtResource("1_ctdir")
|
||||||
dragon_speed = 100.0
|
dragon_speed_min = 50.0
|
||||||
|
dragon_speed_max = 120.0
|
||||||
dragon = NodePath("Dragon")
|
dragon = NodePath("Dragon")
|
||||||
draggable = NodePath("DragDropDetector")
|
draggable = NodePath("DragDropDetector")
|
||||||
|
|
||||||
|
|
|
@ -10,11 +10,11 @@ func _init(dragon: PackedScene, viewport: Viewport, window: Window) -> void:
|
||||||
_dragon_template = dragon
|
_dragon_template = dragon
|
||||||
|
|
||||||
|
|
||||||
func instantiate(position: Vector2, hat: Texture2D, shirt: Texture2D, shoes: Texture2D, dragon_name: String, drag: bool) -> Node:
|
func instantiate(position: Vector2, hat: Texture2D, shirt: Texture2D, shoes: Texture2D, drag: bool) -> Node:
|
||||||
if drag == false:
|
if drag == false:
|
||||||
return _instantiate_dragon(position, hat, shirt, shoes, dragon_name, drag)
|
return _instantiate_dragon(position, hat, shirt, shoes, drag)
|
||||||
var relative_position: Vector2i = _calculate_relative_position(position)
|
var relative_position: Vector2i = _calculate_relative_position(position)
|
||||||
return _instantiate_dragon(relative_position, hat, shirt, shoes, dragon_name, drag)
|
return _instantiate_dragon(relative_position, hat, shirt, shoes, drag)
|
||||||
|
|
||||||
|
|
||||||
func _calculate_window_scale() -> Vector2:
|
func _calculate_window_scale() -> Vector2:
|
||||||
|
@ -29,7 +29,7 @@ func _calculate_relative_position(position: Vector2) -> Vector2i:
|
||||||
return Vector2i(Vector2(position) * scale)
|
return Vector2i(Vector2(position) * scale)
|
||||||
|
|
||||||
|
|
||||||
func _instantiate_dragon(relative_position: Vector2i, hat: Texture2D, shirt: Texture2D, shoes: Texture2D, dragon_name: String, drag: bool) -> Node:
|
func _instantiate_dragon(relative_position: Vector2i, hat: Texture2D, shirt: Texture2D, shoes: Texture2D, drag: bool) -> Node:
|
||||||
var dragon: Dragon = _dragon_template.instantiate()
|
var dragon: Dragon = _dragon_template.instantiate()
|
||||||
|
|
||||||
var window_position: Vector2i = DisplayServer.window_get_position()
|
var window_position: Vector2i = DisplayServer.window_get_position()
|
||||||
|
@ -40,7 +40,6 @@ func _instantiate_dragon(relative_position: Vector2i, hat: Texture2D, shirt: Tex
|
||||||
else:
|
else:
|
||||||
dragon.position = window_position + relative_position - dragon.size / 2
|
dragon.position = window_position + relative_position - dragon.size / 2
|
||||||
dragon.dress(hat, shirt, shoes)
|
dragon.dress(hat, shirt, shoes)
|
||||||
dragon.set_dragon_name(dragon_name)
|
|
||||||
|
|
||||||
var size: float = _calculate_window_scale().y
|
var size: float = _calculate_window_scale().y
|
||||||
dragon.main_window_rect = Rect2i(window_position, window_size)
|
dragon.main_window_rect = Rect2i(window_position, window_size)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue