diff --git a/.vscode/launch.json b/.vscode/launch.json
new file mode 100644
index 0000000..23c5875
--- /dev/null
+++ b/.vscode/launch.json
@@ -0,0 +1,18 @@
+{
+ "version": "0.2.0",
+ "configurations": [
+ {
+ "name": "Launch Project",
+ "type": "godot",
+ "request": "launch",
+ "project": "${workspaceFolder}",
+ },
+ {
+ "name": "Launch Scene",
+ "type": "godot",
+ "request": "launch",
+ "scene": "current",
+ "project": "${workspaceFolder}",
+ }
+ ]
+}
\ No newline at end of file
diff --git a/NOTICE.md b/NOTICE.md
index 7af921e..73872be 100644
--- a/NOTICE.md
+++ b/NOTICE.md
@@ -8,12 +8,12 @@ This project uses the following external assets:
| `./temp/tollbell.mp3` | https://freesound.org/people/sdroliasnick/sounds/731270/ | CC0 |
| `./entities/sheep_drag.wav` | https://freesound.org/people/michaelperfect/sounds/710298/ | CC0 |
| `./temp/click&pop.wav` | https://freesound.org/people/GammaGool/sounds/730488/ | CC0 |
-| `./temp/pop.wav` | https://freesound.org/people/NovaSoundTechnology/sounds/727104/ | CC0 |
+| `./entities/monocle_drag.wav` | https://freesound.org/people/NovaSoundTechnology/sounds/727104/ | CC0 |
| `./temp/mouth_pop.wav` | https://freesound.org/people/igaopuromalte/sounds/725453/ | Attribution 4 |
-| `./temp/puff.wav` | https://freesound.org/people/JustInvoke/sounds/446124/ | Attribution 4 |
+| `./entities/fall.ogg` | https://freesound.org/people/JustInvoke/sounds/446124/ | Attribution 4 |
| `./temp/place.wav` | https://freesound.org/people/Planman/sounds/208111/ | CC0 |
-| `./temp/gore.wav` | https://freesound.org/people/MinecraftGamerLR/sounds/728695/ | Attribution 4 |
-| `./temp/bones.wav` | https://freesound.org/people/cliftonmcarlson/sounds/392883/ | CC0 |
+| `./entities/imp_eat.ogg` | https://freesound.org/people/MinecraftGamerLR/sounds/728695/ | Attribution 4 |
+| `./entities/skull_pickup.wav` | https://freesound.org/people/cliftonmcarlson/sounds/392883/ | CC0 |
| `./temp/metallic_whistle.wav` | https://freesound.org/people/furbyguy/sounds/365643/| Attribution 3|
| `./temp/upgradeselect.wav` | https://freesound.org/people/TechspiredMinds/sounds/729216/| Attribution 4|
| `./temp/upgrade.wav` | https://freesound.org/people/colorsCrimsonTears/sounds/607409/ | CC0 |
@@ -22,7 +22,7 @@ This project uses the following external assets:
| `./temp/arcade_cancel.flac` | https://freesound.org/people/plasterbrain/sounds/464912/ | CC0 |
| `./temp/cancel.wav` | https://freesound.org/people/Kagateni/sounds/571510/ | CC0 |
| `./temp/monster_bite.wav` | https://freesound.org/people/OGsoundFX/sounds/423010/ | Attribution 4 |
-| `./temp/tank.wav` | https://freesound.org/people/JarredGibb/sounds/217273/ | CC0 |
+| `./entities/imp_drag.wav` | https://freesound.org/people/JarredGibb/sounds/217273/ | CC0 |
| `./temp/demon_dying.wav` | https://freesound.org/people/THE_bizniss/sounds/37823/ | Attribution 3 |
| `./entities/coin.ogg` | https://freesound.org/people/forrisday/sounds/214509/ | Attribution 4 |
| `./behaviours/*.svg` | https://fontawesome.com/ | CC-BY 4.0 |
diff --git a/behaviours/collectable.gd b/behaviours/collectable.gd
deleted file mode 100644
index 42cd58b..0000000
--- a/behaviours/collectable.gd
+++ /dev/null
@@ -1,18 +0,0 @@
-@icon("res://behaviours/collectable.svg")
-extends Area2D
-class_name Collectable
-
-## Emits [signal collected] when the mouse enters the given [CollisionShape2D].
-
-
-signal collected
-
-@export var qty: int = 1
-@export var tag: StringName = &""
-
-
-func _on_mouse_entered() -> void:
- collected.emit(tag)
-
-func _on_collected() -> void:
- Log.p(self, "Collected: %sx %s" % [qty, tag])
diff --git a/behaviours/collectable.tscn b/behaviours/collectable.tscn
deleted file mode 100644
index 775501a..0000000
--- a/behaviours/collectable.tscn
+++ /dev/null
@@ -1,9 +0,0 @@
-[gd_scene load_steps=2 format=3 uid="uid://dj72yshd25ucx"]
-
-[ext_resource type="Script" path="res://behaviours/collectable.gd" id="1_p0pc3"]
-
-[node name="Collectable" type="Area2D"]
-script = ExtResource("1_p0pc3")
-
-[connection signal="collected" from="." to="." method="_on_collected"]
-[connection signal="mouse_entered" from="." to="." method="_on_mouse_entered"]
diff --git a/behaviours/collectible.gd b/behaviours/collectible.gd
new file mode 100644
index 0000000..63d85c4
--- /dev/null
+++ b/behaviours/collectible.gd
@@ -0,0 +1,17 @@
+@icon("res://behaviours/collectible.svg")
+extends Node
+class_name Collectible
+
+
+## How many of that item this [Collectible] represents.
+@export var quantity: int = 1
+
+## What kind of item this [Collectible] represents.
+@export var kind: StringName = &""
+
+
+@onready var game: MainGame = MainGame.get_via_group(self)
+
+
+func apply():
+ game.inventory.get_counter(kind).increase(quantity)
\ No newline at end of file
diff --git a/behaviours/collectable.svg b/behaviours/collectible.svg
similarity index 92%
rename from behaviours/collectable.svg
rename to behaviours/collectible.svg
index 1625126..699f33f 100644
--- a/behaviours/collectable.svg
+++ b/behaviours/collectible.svg
@@ -3,7 +3,7 @@
viewBox="0 0 512 512"
version="1.1"
id="svg1"
- sodipodi:docname="hand.svg"
+ sodipodi:docname="collectable.svg"
width="16"
height="16"
inkscape:version="1.3.2 (091e20ef0f, 2023-11-25, custom)"
@@ -23,8 +23,8 @@
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:zoom="1.1642403"
- inkscape:cx="350.01366"
- inkscape:cy="213.44391"
+ inkscape:cx="350.01365"
+ inkscape:cy="-130.12778"
inkscape:window-width="1920"
inkscape:window-height="1020"
inkscape:window-x="1280"
@@ -35,5 +35,5 @@
+ style="fill:#e0e0e0;fill-opacity:1" />
diff --git a/behaviours/collectable.svg.import b/behaviours/collectible.svg.import
similarity index 74%
rename from behaviours/collectable.svg.import
rename to behaviours/collectible.svg.import
index 70b9a6e..f6b10da 100644
--- a/behaviours/collectable.svg.import
+++ b/behaviours/collectible.svg.import
@@ -3,15 +3,15 @@
importer="texture"
type="CompressedTexture2D"
uid="uid://ds6w6y6v8ywg2"
-path="res://.godot/imported/collectable.svg-5b05e2ea83b32a2349a97b4d9981d066.ctex"
+path="res://.godot/imported/collectible.svg-c540ac452c425e9fd16afd6982ebfbf2.ctex"
metadata={
"vram_texture": false
}
[deps]
-source_file="res://behaviours/collectable.svg"
-dest_files=["res://.godot/imported/collectable.svg-5b05e2ea83b32a2349a97b4d9981d066.ctex"]
+source_file="res://behaviours/collectible.svg"
+dest_files=["res://.godot/imported/collectible.svg-c540ac452c425e9fd16afd6982ebfbf2.ctex"]
[params]
diff --git a/behaviours/collectible.tscn b/behaviours/collectible.tscn
new file mode 100644
index 0000000..906e7e5
--- /dev/null
+++ b/behaviours/collectible.tscn
@@ -0,0 +1,6 @@
+[gd_scene load_steps=2 format=3 uid="uid://dj72yshd25ucx"]
+
+[ext_resource type="Script" path="res://behaviours/collectible.gd" id="1_5ipmg"]
+
+[node name="Collectible" type="Node"]
+script = ExtResource("1_5ipmg")
diff --git a/behaviours/cursor_detector.gd b/behaviours/cursor_detector.gd
new file mode 100644
index 0000000..a80f04f
--- /dev/null
+++ b/behaviours/cursor_detector.gd
@@ -0,0 +1,24 @@
+@icon("res://behaviours/cursor_detector.svg")
+extends Area2D
+class_name CursorDetector
+
+
+signal cursor_entered(cursor: Cursor)
+signal cursor_exited(cursor: Cursor)
+
+
+var mouse_inside = false
+
+
+func _on_area_entered(body: Area2D) -> void:
+ if body is Cursor:
+ mouse_inside = true
+ cursor_entered.emit(body)
+
+func _on_area_exited(body: Area2D) -> void:
+ if body is Cursor:
+ mouse_inside = true
+ cursor_exited.emit(body)
+
+func log_cursor(cursor: Cursor) -> void:
+ Log.p(self, "Cursor: %s" % cursor)
diff --git a/behaviours/hover_detector.svg b/behaviours/cursor_detector.svg
similarity index 100%
rename from behaviours/hover_detector.svg
rename to behaviours/cursor_detector.svg
diff --git a/behaviours/hover_detector.svg.import b/behaviours/cursor_detector.svg.import
similarity index 73%
rename from behaviours/hover_detector.svg.import
rename to behaviours/cursor_detector.svg.import
index b27371a..5467a48 100644
--- a/behaviours/hover_detector.svg.import
+++ b/behaviours/cursor_detector.svg.import
@@ -3,15 +3,15 @@
importer="texture"
type="CompressedTexture2D"
uid="uid://6wpumqhdov4r"
-path="res://.godot/imported/hover_detector.svg-3bfd5bde28e59dd82344da683ff70f2d.ctex"
+path="res://.godot/imported/cursor_detector.svg-15ede4c1c6083de1d2f8a8ceb4ab532a.ctex"
metadata={
"vram_texture": false
}
[deps]
-source_file="res://behaviours/hover_detector.svg"
-dest_files=["res://.godot/imported/hover_detector.svg-3bfd5bde28e59dd82344da683ff70f2d.ctex"]
+source_file="res://behaviours/cursor_detector.svg"
+dest_files=["res://.godot/imported/cursor_detector.svg-15ede4c1c6083de1d2f8a8ceb4ab532a.ctex"]
[params]
diff --git a/behaviours/cursor_detector.tscn b/behaviours/cursor_detector.tscn
new file mode 100644
index 0000000..d5cf13a
--- /dev/null
+++ b/behaviours/cursor_detector.tscn
@@ -0,0 +1,13 @@
+[gd_scene load_steps=2 format=3 uid="uid://cbg5kgwxusvxf"]
+
+[ext_resource type="Script" path="res://behaviours/cursor_detector.gd" id="1_4hcxj"]
+
+[node name="CursorDetector" type="Area2D"]
+collision_layer = 0
+collision_mask = 64
+input_pickable = false
+monitorable = false
+script = ExtResource("1_4hcxj")
+
+[connection signal="area_entered" from="." to="." method="_on_area_entered"]
+[connection signal="area_exited" from="." to="." method="_on_area_exited"]
diff --git a/behaviours/draggable.gd b/behaviours/draggable.gd
index c02fd6b..d52eaad 100644
--- a/behaviours/draggable.gd
+++ b/behaviours/draggable.gd
@@ -1,34 +1,19 @@
+@icon("res://behaviours/draggable.svg")
extends Area2D
class_name Draggable
-signal move(movement: Vector2)
-signal dragged
+signal dragged(cursor: Cursor)
signal dropped
-@onready var mover: Node2D = $"MatchMousePosition"
-
-var being_dragged: bool:
- get:
- return being_dragged
- set(value):
- being_dragged = value
- mover.set_process(being_dragged)
- mover.set_physics_process(being_dragged)
+var being_dragged: bool = false
-func drag():
+func drag(cursor: Cursor):
being_dragged = true
- dragged.emit()
+ dragged.emit(cursor)
func drop():
being_dragged = false
dropped.emit()
-
-
-func _ready():
- being_dragged = false
-
-func _on_move(movement: Vector2):
- move.emit(movement)
diff --git a/behaviours/draggable.svg b/behaviours/draggable.svg
new file mode 100644
index 0000000..2462527
--- /dev/null
+++ b/behaviours/draggable.svg
@@ -0,0 +1,39 @@
+
+
diff --git a/behaviours/edible_tracker.svg.import b/behaviours/draggable.svg.import
similarity index 71%
rename from behaviours/edible_tracker.svg.import
rename to behaviours/draggable.svg.import
index b8c06f4..c2672cd 100644
--- a/behaviours/edible_tracker.svg.import
+++ b/behaviours/draggable.svg.import
@@ -2,16 +2,16 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://8443tt517pkv"
-path="res://.godot/imported/edible_tracker.svg-9169f9c07be35f707b3c167799ba3a76.ctex"
+uid="uid://bepjyaq1y3g7w"
+path="res://.godot/imported/draggable.svg-7f8260afa88b76990683b55fd9af07eb.ctex"
metadata={
"vram_texture": false
}
[deps]
-source_file="res://behaviours/edible_tracker.svg"
-dest_files=["res://.godot/imported/edible_tracker.svg-9169f9c07be35f707b3c167799ba3a76.ctex"]
+source_file="res://behaviours/draggable.svg"
+dest_files=["res://.godot/imported/draggable.svg-7f8260afa88b76990683b55fd9af07eb.ctex"]
[params]
diff --git a/behaviours/draggable.tscn b/behaviours/draggable.tscn
index 60e1f2c..659366f 100644
--- a/behaviours/draggable.tscn
+++ b/behaviours/draggable.tscn
@@ -1,15 +1,10 @@
-[gd_scene load_steps=3 format=3 uid="uid://dijcjahkddudv"]
+[gd_scene load_steps=2 format=3 uid="uid://dijcjahkddudv"]
[ext_resource type="Script" path="res://behaviours/draggable.gd" id="1_hdedq"]
-[ext_resource type="PackedScene" uid="uid://bvrxvrjlo5130" path="res://behaviours/move_towards_mouse.tscn" id="2_gi6xd"]
[node name="Draggable" type="Area2D"]
-collision_layer = 0
+collision_layer = 8
collision_mask = 0
+input_pickable = false
+monitoring = false
script = ExtResource("1_hdedq")
-
-[node name="MatchMousePosition" parent="." instance=ExtResource("2_gi6xd")]
-scale = Vector2(10000, 10000)
-speed = 3600.0
-
-[connection signal="move" from="MatchMousePosition" to="." method="_on_move"]
diff --git a/behaviours/eat_target.gd b/behaviours/eat_target.gd
deleted file mode 100644
index 3ffd6d2..0000000
--- a/behaviours/eat_target.gd
+++ /dev/null
@@ -1,37 +0,0 @@
-extends Node2D
-class_name EatTarget
-
-
-signal eaten(target: Node2D)
-signal move(movement: Vector2)
-
-@export var tag: StringName:
- get:
- return tag
- set(value):
- tag = value
- if hunt_target != null:
- hunt_target.tag = value
- if eater != null:
- eater.tag = value
-
-
-@onready var hunt_target: HuntTarget = $"HuntTarget"
-@onready var eater: Eater = $"Eater"
-@onready var move_towards: MoveTowardsTarget = $"MoveTowardsTarget"
-
-func _ready():
- hunt_target.tag = tag
- eater.tag = tag
-
-func _on_target_selected(body: Node2D) -> void:
- move_towards.target = body
-
-func _on_target_abandoned(_body: Node2D) -> void:
- move_towards.target = null
-
-func _on_eater_eaten(edible):
- eaten.emit(edible)
-
-func _on_move_towards_target_move(movement):
- move.emit(movement)
diff --git a/behaviours/eat_target.tscn b/behaviours/eat_target.tscn
deleted file mode 100644
index 53ab7a7..0000000
--- a/behaviours/eat_target.tscn
+++ /dev/null
@@ -1,23 +0,0 @@
-[gd_scene load_steps=5 format=3 uid="uid://b7bdlh5akhi8s"]
-
-[ext_resource type="Script" path="res://behaviours/eat_target.gd" id="1_tlnlt"]
-[ext_resource type="PackedScene" uid="uid://dxmodn8mbvw0i" path="res://behaviours/hunt_target.tscn" id="2_c8wdv"]
-[ext_resource type="PackedScene" uid="uid://jg7qkbswgqjc" path="res://behaviours/eater.tscn" id="3_ir2yh"]
-[ext_resource type="PackedScene" uid="uid://kceb2v2dm0qn" path="res://behaviours/move_towards_target.tscn" id="4_1qc2q"]
-
-[node name="EatTarget" type="Node2D"]
-script = ExtResource("1_tlnlt")
-
-[node name="HuntTarget" parent="." instance=ExtResource("2_c8wdv")]
-scale = Vector2(16, 16)
-give_up_secs = 5.0
-
-[node name="Eater" parent="." instance=ExtResource("3_ir2yh")]
-scale = Vector2(2.5, 2.5)
-
-[node name="MoveTowardsTarget" parent="." instance=ExtResource("4_1qc2q")]
-
-[connection signal="target_abandoned" from="HuntTarget" to="." method="_on_target_abandoned"]
-[connection signal="target_selected" from="HuntTarget" to="." method="_on_target_selected"]
-[connection signal="eaten" from="Eater" to="." method="_on_eater_eaten"]
-[connection signal="move" from="MoveTowardsTarget" to="." method="_on_move_towards_target_move"]
diff --git a/behaviours/eater.gd b/behaviours/eater.gd
index 4bd5392..2a0c563 100644
--- a/behaviours/eater.gd
+++ b/behaviours/eater.gd
@@ -11,6 +11,9 @@ signal eaten(edible: Edible)
@export var acceptable_diets: Array[StringName] = []
+func log_eaten(edible: Edible) -> void:
+ Log.p(self, "Eaten: %s" % edible)
+
func _on_body_entered(body: Node2D) -> void:
var edibles: Array = body.find_children("Edible", "Edible", false, false)
@@ -18,7 +21,3 @@ func _on_body_entered(body: Node2D) -> void:
if edible.diet in acceptable_diets:
eaten.emit(edible)
edible.eat()
-
-
-func _on_eaten(edible: Edible) -> void:
- Log.p(self, "Eaten: %s" % edible)
diff --git a/behaviours/eater.tscn b/behaviours/eater.tscn
index d1f79ab..076639c 100644
--- a/behaviours/eater.tscn
+++ b/behaviours/eater.tscn
@@ -5,8 +5,8 @@
[node name="Eater" type="Area2D"]
collision_layer = 0
collision_mask = 8
+input_pickable = false
monitorable = false
script = ExtResource("1_urx5y")
[connection signal="body_entered" from="." to="." method="_on_body_entered"]
-[connection signal="eaten" from="." to="." method="_on_eaten"]
diff --git a/behaviours/edible.gd b/behaviours/edible.gd
index 5926b07..88bc469 100644
--- a/behaviours/edible.gd
+++ b/behaviours/edible.gd
@@ -14,6 +14,3 @@ signal eaten
func eat():
eaten.emit()
-
-func _on_eaten() -> void:
- Log.p(self, "Got eaten.")
diff --git a/behaviours/edible.tscn b/behaviours/edible.tscn
index 5a4b405..d8fa24f 100644
--- a/behaviours/edible.tscn
+++ b/behaviours/edible.tscn
@@ -4,5 +4,3 @@
[node name="Edible" type="Node"]
script = ExtResource("1_l6vtr")
-
-[connection signal="eaten" from="." to="." method="_on_eaten"]
diff --git a/behaviours/edible_tracker.gd b/behaviours/edible_tracker.gd
deleted file mode 100644
index bcf1bef..0000000
--- a/behaviours/edible_tracker.gd
+++ /dev/null
@@ -1,34 +0,0 @@
-@icon("res://behaviours/edible_tracker.svg")
-extends Area2D
-class_name EdibleTracker
-
-## Keeps track of what [Edible]s are inside the area.
-
-
-signal tracked(body: Node2D)
-signal untracked(body: Node2D)
-
-
-@export var acceptable_diets: Array[StringName] = []
-
-var tracking: Array = []
-
-
-func _on_body_entered(body: Node2D) -> void:
- var edibles: Array = body.find_children("Edible", "Edible", false, false)
- for edible in edibles:
- if edible.tag in acceptable_diets:
- tracking.push_back(body)
- tracked.emit(body)
-
-func _on_body_exited(body: Node2D) -> void:
- if body in tracking:
- tracking.erase(body)
- untracked.emit(body)
-
-
-func _on_tracked(body: Node2D) -> void:
- Log.p(self, "Tracking a new target: %s" % body)
-
-func _on_untracked(body:Node2D) -> void:
- Log.p(self, "Not tracking anymore target: %s" % body)
diff --git a/behaviours/edible_tracker.svg b/behaviours/edible_tracker.svg
deleted file mode 100644
index 34115c7..0000000
--- a/behaviours/edible_tracker.svg
+++ /dev/null
@@ -1,39 +0,0 @@
-
-
diff --git a/behaviours/edible_tracker.tscn b/behaviours/edible_tracker.tscn
deleted file mode 100644
index 2d75fbd..0000000
--- a/behaviours/edible_tracker.tscn
+++ /dev/null
@@ -1,11 +0,0 @@
-[gd_scene load_steps=2 format=3 uid="uid://ctpn4hvkhxoi3"]
-
-[ext_resource type="Script" path="res://behaviours/edible_tracker.gd" id="1_vo18u"]
-
-[node name="EdibleTracker" type="Area2D"]
-script = ExtResource("1_vo18u")
-
-[connection signal="body_entered" from="." to="." method="_on_body_entered"]
-[connection signal="body_exited" from="." to="." method="_on_body_exited"]
-[connection signal="tracked" from="." to="." method="_on_tracked"]
-[connection signal="untracked" from="." to="." method="_on_untracked"]
diff --git a/behaviours/hover_detector.gd b/behaviours/hover_detector.gd
deleted file mode 100644
index 616e72a..0000000
--- a/behaviours/hover_detector.gd
+++ /dev/null
@@ -1,13 +0,0 @@
-@icon("res://behaviours/hover_detector.svg")
-extends Area2D
-class_name HoverDetector
-
-
-var mouse_inside = false
-
-
-func _on_mouse_entered() -> void:
- mouse_inside = true
-
-func _on_mouse_exited() -> void:
- mouse_inside = false
diff --git a/behaviours/hover_detector.tscn b/behaviours/hover_detector.tscn
deleted file mode 100644
index b6800b0..0000000
--- a/behaviours/hover_detector.tscn
+++ /dev/null
@@ -1,11 +0,0 @@
-[gd_scene load_steps=2 format=3 uid="uid://cbg5kgwxusvxf"]
-
-[ext_resource type="Script" path="res://behaviours/hover_detector.gd" id="1_51m5p"]
-
-[node name="HoverDetector" type="Area2D"]
-collision_mask = 0
-monitorable = false
-script = ExtResource("1_51m5p")
-
-[connection signal="mouse_entered" from="." to="." method="_on_mouse_entered"]
-[connection signal="mouse_exited" from="." to="." method="_on_mouse_exited"]
diff --git a/behaviours/hunt_target.gd b/behaviours/hunt_target.gd
deleted file mode 100644
index cdd7f9c..0000000
--- a/behaviours/hunt_target.gd
+++ /dev/null
@@ -1,55 +0,0 @@
-extends Node2D
-class_name HuntTarget
-
-
-signal target_selected(target: Node2D)
-signal target_abandoned(target: Node2D)
-
-
-@export var tag: StringName:
- get:
- return tag
- set(value):
- tag = value
- if hunter != null:
- hunter.tag = value
-
-@export var give_up_secs: float = 5.0
-
-@onready var give_up_timer: Timer = $"GiveUpTimer"
-@onready var hunter: Hunter = $"Hunter"
-
-var target: Node2D = null
-
-
-func pick_new_target():
- if hunter.possible_targets.is_empty():
- return
-
- var idx = Random.rng.randi_range(0, len(hunter.possible_targets) - 1)
- target = hunter.possible_targets[idx]
- target_selected.emit(target)
- give_up_timer.start(give_up_secs)
-
-func _ready():
- hunter.tag = tag
-
-func _on_hunter_tracked(_body: Node2D):
- if target == null:
- pick_new_target()
-
-func _on_hunter_untracked(body: Node2D):
- if body == target:
- target = null
- target_abandoned.emit(body)
- pick_new_target()
-
-func _on_give_up_timer_timeout() -> void:
- target = null
- pick_new_target()
-
-func _on_target_selected(body: Node2D) -> void:
- Log.p(self, "Target selected: %s" % body)
-
-func _on_target_abandoned(body: Node2D) -> void:
- Log.p(self, "Target abandoned: %s" % body)
diff --git a/behaviours/hunt_target.tscn b/behaviours/hunt_target.tscn
deleted file mode 100644
index dc8bf57..0000000
--- a/behaviours/hunt_target.tscn
+++ /dev/null
@@ -1,18 +0,0 @@
-[gd_scene load_steps=3 format=3 uid="uid://dxmodn8mbvw0i"]
-
-[ext_resource type="Script" path="res://behaviours/hunt_target.gd" id="1_1ex7u"]
-[ext_resource type="PackedScene" uid="uid://ctpn4hvkhxoi3" path="res://behaviours/edible_tracker.tscn" id="2_vjdtc"]
-
-[node name="HuntTarget" type="Node2D"]
-script = ExtResource("1_1ex7u")
-give_up_secs = null
-
-[node name="Hunter" parent="." instance=ExtResource("2_vjdtc")]
-
-[node name="GiveUpTimer" type="Timer" parent="."]
-
-[connection signal="target_abandoned" from="." to="." method="_on_target_abandoned"]
-[connection signal="target_selected" from="." to="." method="_on_target_selected"]
-[connection signal="tracked" from="Hunter" to="." method="_on_hunter_tracked"]
-[connection signal="untracked" from="Hunter" to="." method="_on_hunter_untracked"]
-[connection signal="timeout" from="GiveUpTimer" to="." method="_on_give_up_timer_timeout"]
diff --git a/behaviours/move.gd b/behaviours/move.gd
new file mode 100644
index 0000000..fb033cd
--- /dev/null
+++ b/behaviours/move.gd
@@ -0,0 +1,22 @@
+@icon("res://behaviours/move.svg")
+extends Node2D
+class_name Move
+
+
+signal move(norm: Vector2)
+signal move_toggled(value: bool)
+signal move_enabled
+signal move_disabled
+
+## Whether this component should emit [signal move].
+@export var enabled: bool = true:
+ get:
+ return enabled
+ set(value):
+ if enabled != value:
+ enabled = value
+ move_toggled.emit(value)
+ if value:
+ move_enabled.emit()
+ else:
+ move_disabled.emit()
diff --git a/behaviours/move.svg b/behaviours/move.svg
new file mode 100644
index 0000000..af25ecb
--- /dev/null
+++ b/behaviours/move.svg
@@ -0,0 +1,39 @@
+
+
diff --git a/behaviours/move.svg.import b/behaviours/move.svg.import
new file mode 100644
index 0000000..4c4d4a8
--- /dev/null
+++ b/behaviours/move.svg.import
@@ -0,0 +1,37 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://d10wobjiuh1mm"
+path="res://.godot/imported/move.svg-6291495a0c7bf9c3c43cbea535114f1a.ctex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://behaviours/move.svg"
+dest_files=["res://.godot/imported/move.svg-6291495a0c7bf9c3c43cbea535114f1a.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1
+svg/scale=1.0
+editor/scale_with_editor_scale=false
+editor/convert_colors_with_editor_theme=false
diff --git a/behaviours/move_physics.gd b/behaviours/move_physics.gd
new file mode 100644
index 0000000..bb8524a
--- /dev/null
+++ b/behaviours/move_physics.gd
@@ -0,0 +1,46 @@
+extends Move
+class_name MovePhysics
+
+
+signal dragged(cursor: Cursor)
+signal dropped
+signal fallen
+
+
+@export var acceleration = 1250.0
+@export var drag_damp = 0.4
+@export var drop_damp = 0.05
+@export var drop_epsilon = 16.0
+
+var cursor: Cursor = null
+var falling: bool = false
+
+var velocity := Vector2.ZERO
+
+
+func drag(value: Cursor) -> void:
+ cursor = value
+ dragged.emit(value)
+
+func drop() -> void:
+ cursor = null
+ falling = true
+ dropped.emit()
+
+func fall() -> void:
+ velocity = Vector2.ZERO
+ falling = false
+ fallen.emit()
+
+
+func _physics_process(delta: float) -> void:
+ if enabled:
+ if cursor:
+ var gap = cursor.global_position - global_position
+ velocity += gap * delta * acceleration
+ velocity *= 1.0 - drag_damp
+ else:
+ velocity *= 1.0 - drop_damp
+ if falling and velocity.length() < drop_epsilon:
+ fall()
+ move.emit(velocity * delta)
diff --git a/behaviours/move_physics.tscn b/behaviours/move_physics.tscn
new file mode 100644
index 0000000..2a31113
--- /dev/null
+++ b/behaviours/move_physics.tscn
@@ -0,0 +1,6 @@
+[gd_scene load_steps=2 format=3 uid="uid://rx24bppccih7"]
+
+[ext_resource type="Script" path="res://behaviours/move_physics.gd" id="1_u02i3"]
+
+[node name="MoveTowardsPhysics" type="Node2D"]
+script = ExtResource("1_u02i3")
diff --git a/behaviours/move_straight.gd b/behaviours/move_straight.gd
new file mode 100644
index 0000000..4e6ec30
--- /dev/null
+++ b/behaviours/move_straight.gd
@@ -0,0 +1,35 @@
+extends Move
+class_name MoveStraight
+
+## A [Move] that moves in a fixed direction.
+
+
+signal changed_direction(new: Vector2)
+
+
+@export var speed: float = 100.0
+
+@export var direction: Vector2:
+ get:
+ return direction
+ set(value):
+ direction = value
+ changed_direction.emit(direction)
+
+
+func set_direction(value: Vector2) -> void:
+ direction = value
+
+func clear_direction() -> void:
+ direction = Vector2.ZERO
+
+func randomize_direction() -> void:
+ direction = Vector2.from_angle(Random.rng.randf_range(0, 2*PI))
+
+func log_state() -> void:
+ Log.p(self, "Direction: %s | Speed: %s" % [direction, speed])
+
+
+func _physics_process(delta: float) -> void:
+ if enabled:
+ move.emit(direction * delta * speed)
diff --git a/behaviours/move_straight.tscn b/behaviours/move_straight.tscn
new file mode 100644
index 0000000..e176db3
--- /dev/null
+++ b/behaviours/move_straight.tscn
@@ -0,0 +1,6 @@
+[gd_scene load_steps=2 format=3 uid="uid://dk1ipq7dhkhf3"]
+
+[ext_resource type="Script" path="res://behaviours/move_straight.gd" id="1_8yf73"]
+
+[node name="MoveStraight" type="Node2D"]
+script = ExtResource("1_8yf73")
diff --git a/behaviours/move_towards.gd b/behaviours/move_towards.gd
index 952da47..4dad3a0 100644
--- a/behaviours/move_towards.gd
+++ b/behaviours/move_towards.gd
@@ -1,44 +1,38 @@
-extends Node2D
+extends Move
class_name MoveTowards
-signal move(movement: Vector2)
-signal detached
-signal captured
+## A [Move] that moves towards the [field position] of a [field target].
+
+
+signal changed_target(new: Node2D)
@export var speed: float = 100.0
-@export var can_detach: bool = false
+
+@export var target: Node2D = null:
+ get:
+ return target
+ set(value):
+ target = value
+ changed_target.emit(value)
-enum State { DETACHED, CAPTURED }
+func set_target(value: Node2D) -> void:
+ target = value
-var state: State = State.DETACHED
+func clear_target() -> void:
+ target = null
-func get_followed_global_position():
- return Vector2.ZERO # OVERRIDE ME!
-
-
-func get_followed_mouse_position():
- var global_followed_position: Vector2 = get_followed_global_position()
- var relative_followed_position: Vector2 = global_followed_position - global_position
- return relative_followed_position
+func log_target() -> void:
+ Log.p(self, "Target: %s" % target)
func _physics_process(delta: float) -> void:
- match state:
- State.CAPTURED:
- var relative_followed_position: Vector2 = get_followed_mouse_position()
- var direction: Vector2 = position.direction_to(relative_followed_position)
- var actual_speed: float = min(delta * speed, relative_followed_position.length()) # Don't overshoot.
- var movement: Vector2 = direction * actual_speed
- move.emit(movement)
-
-func _on_capture_area_mouse_entered() -> void:
- state = State.CAPTURED
- captured.emit()
-
-func _on_capture_area_mouse_exited() -> void:
- if can_detach:
- state = State.DETACHED
- detached.emit()
+ if enabled:
+ if target:
+ var gap = target.global_position - global_position
+ var norm = gap.normalized()
+ move.emit(norm * delta * speed)
+ else:
+ move.emit(Vector2.ZERO)
diff --git a/behaviours/move_towards.tscn b/behaviours/move_towards.tscn
new file mode 100644
index 0000000..41b4c4a
--- /dev/null
+++ b/behaviours/move_towards.tscn
@@ -0,0 +1,6 @@
+[gd_scene load_steps=2 format=3 uid="uid://cml7rqvyfuagx"]
+
+[ext_resource type="Script" path="res://behaviours/move_towards.gd" id="1_256ue"]
+
+[node name="MoveTowards" type="Node2D"]
+script = ExtResource("1_256ue")
diff --git a/behaviours/move_towards_mouse.gd b/behaviours/move_towards_mouse.gd
deleted file mode 100644
index 4bbcee7..0000000
--- a/behaviours/move_towards_mouse.gd
+++ /dev/null
@@ -1,46 +0,0 @@
-extends Node2D
-class_name MoveTowardsMouse
-
-
-signal move(movement: Vector2)
-signal detached
-signal captured
-
-@onready var game := MainGame.get_ancestor(self)
-
-@export var speed: float = 100.0
-@export var can_detach: bool = false
-
-
-enum State { DETACHED, CAPTURED }
-
-var state: State = State.DETACHED
-
-func get_followed_global_position():
- return game.camera.get_global_mouse_position()
-
-
-func get_followed_mouse_position():
- var global_followed_position: Vector2 = get_followed_global_position()
- var relative_followed_position: Vector2 = global_followed_position - global_position
- return relative_followed_position
-
-
-func _physics_process(delta: float) -> void:
- match state:
- State.CAPTURED:
- var relative_followed_position: Vector2 = get_followed_mouse_position()
- var direction: Vector2 = position.direction_to(relative_followed_position)
- var actual_speed: float = min(delta * speed, relative_followed_position.length()) # Don't overshoot.
- var movement: Vector2 = direction * actual_speed
- move.emit(movement)
-
-func _on_capture_area_mouse_entered() -> void:
- state = State.CAPTURED
- captured.emit()
-
-func _on_capture_area_mouse_exited() -> void:
- if can_detach:
- state = State.DETACHED
- detached.emit()
-
diff --git a/behaviours/move_towards_mouse.tscn b/behaviours/move_towards_mouse.tscn
deleted file mode 100644
index ab15a6f..0000000
--- a/behaviours/move_towards_mouse.tscn
+++ /dev/null
@@ -1,12 +0,0 @@
-[gd_scene load_steps=3 format=3 uid="uid://bvrxvrjlo5130"]
-
-[ext_resource type="Script" path="res://behaviours/move_towards_mouse.gd" id="1_nbja1"]
-[ext_resource type="PackedScene" uid="uid://cbg5kgwxusvxf" path="res://behaviours/hover_detector.tscn" id="2_qru2e"]
-
-[node name="MoveTowardsMouse" type="Node2D"]
-script = ExtResource("1_nbja1")
-
-[node name="CaptureArea" parent="." instance=ExtResource("2_qru2e")]
-
-[connection signal="mouse_entered" from="CaptureArea" to="." method="_on_capture_area_mouse_entered"]
-[connection signal="mouse_exited" from="CaptureArea" to="." method="_on_capture_area_mouse_exited"]
diff --git a/behaviours/move_towards_target.gd b/behaviours/move_towards_target.gd
deleted file mode 100644
index c519780..0000000
--- a/behaviours/move_towards_target.gd
+++ /dev/null
@@ -1,29 +0,0 @@
-extends Node2D
-class_name MoveTowardsTarget
-
-
-signal move(movement: Vector2)
-
-
-@export var speed: float = 100.0
-@export var target: Node2D
-
-
-func get_followed_global_position():
- return target.global_position
-
-
-func get_followed_mouse_position():
- var global_followed_position: Vector2 = get_followed_global_position()
- var relative_followed_position: Vector2 = global_followed_position - global_position
- return relative_followed_position
-
-
-func _physics_process(delta: float) -> void:
- if target == null:
- return
- var relative_followed_position: Vector2 = get_followed_mouse_position()
- var direction: Vector2 = position.direction_to(relative_followed_position)
- var actual_speed: float = min(delta * speed, relative_followed_position.length()) # Don't overshoot.
- var movement: Vector2 = direction * actual_speed
- move.emit(movement)
diff --git a/behaviours/move_towards_target.tscn b/behaviours/move_towards_target.tscn
deleted file mode 100644
index d04e146..0000000
--- a/behaviours/move_towards_target.tscn
+++ /dev/null
@@ -1,6 +0,0 @@
-[gd_scene load_steps=2 format=3 uid="uid://kceb2v2dm0qn"]
-
-[ext_resource type="Script" path="res://behaviours/move_towards_target.gd" id="1_703gy"]
-
-[node name="MoveTowardsTarget" type="Node2D"]
-script = ExtResource("1_703gy")
diff --git a/behaviours/priority.gd b/behaviours/priority.gd
new file mode 100644
index 0000000..54509b1
--- /dev/null
+++ b/behaviours/priority.gd
@@ -0,0 +1,69 @@
+@icon("res://behaviours/priority.svg")
+extends Node
+class_name Priority
+
+
+## Keeps track of the object's priority for [SamplerPriority] purposes.
+
+
+## Emitted when the priority is changed.
+signal priority_changed(new: int, old: int)
+
+## Emitted when the priority is changed. No args are provided to work around a Godot bug.
+signal priority_changed_no_args
+
+
+@export var default_priority: int = 0
+@export var alternative_priority: int = 1
+
+var priority: int = 0:
+ get:
+ return priority
+ set(value):
+ var old = priority
+ priority = value
+ priority_changed.emit(priority, old)
+
+
+## Set [field priority] to [field default_priority].
+func priority_default() -> void:
+ priority = default_priority
+
+## Set [field priority] to [field alternative_priority]
+func priority_alternative() -> void:
+ priority = alternative_priority
+
+## Toggle [field priority] between [field default_priority] and [field alternative_priority].
+func priority_toggle() -> void:
+ if priority == default_priority:
+ priority = alternative_priority
+ else:
+ priority = default_priority
+
+## Set the [field priority] to a specific value.
+func priority_set(value: int):
+ priority = value
+
+## Set the [field priority] to a specific value if the [param variant] is truthy, otherwise set it to a different value.
+##
+## Defaults to using [field alternative_priority] for truthy, and [field default_priority] for falsy
+func priority_conditional(variant: Variant, truthy: int = alternative_priority, falsy: int = default_priority):
+ if variant:
+ priority = truthy
+ else:
+ priority = falsy
+
+## Get the node to which the [field priority] of this one applies to.
+func get_ref() -> Node:
+ return get_parent()
+
+## Log the current [field priority] value.
+func log_priority() -> void:
+ Log.p(self, "Priority: %d" % priority)
+
+
+func _on_priority_changed(_new: int, _old: int) -> void:
+ priority_changed_no_args.emit()
+
+func _ready() -> void:
+ priority = default_priority
diff --git a/behaviours/priority.svg b/behaviours/priority.svg
new file mode 100644
index 0000000..5223e43
--- /dev/null
+++ b/behaviours/priority.svg
@@ -0,0 +1,39 @@
+
+
diff --git a/behaviours/priority.svg.import b/behaviours/priority.svg.import
new file mode 100644
index 0000000..9148364
--- /dev/null
+++ b/behaviours/priority.svg.import
@@ -0,0 +1,37 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://ctc4lx571jksr"
+path="res://.godot/imported/priority.svg-d16c10b6303969bc43c2b8feaccb77ae.ctex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://behaviours/priority.svg"
+dest_files=["res://.godot/imported/priority.svg-d16c10b6303969bc43c2b8feaccb77ae.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1
+svg/scale=1.0
+editor/scale_with_editor_scale=false
+editor/convert_colors_with_editor_theme=false
diff --git a/behaviours/priority.tscn b/behaviours/priority.tscn
new file mode 100644
index 0000000..e240944
--- /dev/null
+++ b/behaviours/priority.tscn
@@ -0,0 +1,8 @@
+[gd_scene load_steps=2 format=3 uid="uid://cm67ko1k6kn4u"]
+
+[ext_resource type="Script" path="res://behaviours/priority.gd" id="1_8u7ji"]
+
+[node name="Priority" type="Node"]
+script = ExtResource("1_8u7ji")
+
+[connection signal="priority_changed" from="." to="." method="_on_priority_changed"]
diff --git a/behaviours/sampler.gd b/behaviours/sampler.gd
new file mode 100644
index 0000000..00b87eb
--- /dev/null
+++ b/behaviours/sampler.gd
@@ -0,0 +1,29 @@
+@icon("res://behaviours/sampler.svg")
+extends Node
+class_name Sampler
+
+
+## Abstract base class for sampling a certain reference among multiple.
+
+
+## [Array] of [Node]s that can be [func sample]d by this [Sampler].
+@export var possibilities: Array[Node] = []
+
+
+## Get a reference.
+func sample() -> Node:
+ Log.e(self, "Not implemented.")
+ return null
+
+## Set the [field enabled] property to true on a [method sample]d node, and to false on all others.
+func enable() -> void:
+ var selected = sample()
+ for possibility in get_all_refs():
+ possibility.enabled = (selected == possibility)
+
+
+## Get all possible nodes referenced by [field possibilities].
+##
+## Useful as it may be overridden by some other [Sampler]s, such as [SamplerPriority].
+func get_all_refs() -> Array[Node]:
+ return possibilities
\ No newline at end of file
diff --git a/behaviours/sampler.svg b/behaviours/sampler.svg
new file mode 100644
index 0000000..de84648
--- /dev/null
+++ b/behaviours/sampler.svg
@@ -0,0 +1,59 @@
+
+
diff --git a/behaviours/sampler.svg.import b/behaviours/sampler.svg.import
new file mode 100644
index 0000000..4b58e6a
--- /dev/null
+++ b/behaviours/sampler.svg.import
@@ -0,0 +1,37 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://cv32pf38ugoh1"
+path="res://.godot/imported/sampler.svg-3634a55299eb9a683092cba4e7d215f9.ctex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://behaviours/sampler.svg"
+dest_files=["res://.godot/imported/sampler.svg-3634a55299eb9a683092cba4e7d215f9.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1
+svg/scale=1.0
+editor/scale_with_editor_scale=false
+editor/convert_colors_with_editor_theme=false
diff --git a/behaviours/sampler_priority.gd b/behaviours/sampler_priority.gd
new file mode 100644
index 0000000..c925afb
--- /dev/null
+++ b/behaviours/sampler_priority.gd
@@ -0,0 +1,28 @@
+extends Sampler
+class_name SamplerPriority
+
+
+## Always sample the object with the highest priority in the queue.
+
+
+## Get a reference.
+func sample() -> Priority:
+ if len(possibilities) == 0:
+ return null
+
+ # FIXME: Change this to something more efficient when needed
+ var highest_possibility: Priority = null
+ for possibility in possibilities:
+ if highest_possibility == null or possibility.priority > highest_possibility.priority:
+ highest_possibility = possibility
+
+ if highest_possibility == null:
+ return null
+
+ return highest_possibility.get_ref()
+
+func get_all_refs() -> Array[Node]:
+ var refs: Array[Node] = []
+ for possibility in possibilities:
+ refs.append(possibility.get_ref())
+ return refs
diff --git a/behaviours/sampler_priority.tscn b/behaviours/sampler_priority.tscn
new file mode 100644
index 0000000..6865ca7
--- /dev/null
+++ b/behaviours/sampler_priority.tscn
@@ -0,0 +1,6 @@
+[gd_scene load_steps=2 format=3 uid="uid://djcwis8ycrq85"]
+
+[ext_resource type="Script" path="res://behaviours/sampler_priority.gd" id="1_jy5r5"]
+
+[node name="SamplerPriority" type="Node"]
+script = ExtResource("1_jy5r5")
diff --git a/behaviours/sampler_random.gd b/behaviours/sampler_random.gd
new file mode 100644
index 0000000..88e4e82
--- /dev/null
+++ b/behaviours/sampler_random.gd
@@ -0,0 +1,11 @@
+extends Sampler
+class_name SamplerRandom
+
+
+## Sample a random reference from the array.
+
+
+func sample() -> Node:
+ if len(possibilities) == 0:
+ return null
+ return Random.sample(possibilities)
diff --git a/behaviours/sampler_random.tscn b/behaviours/sampler_random.tscn
new file mode 100644
index 0000000..5b1695f
--- /dev/null
+++ b/behaviours/sampler_random.tscn
@@ -0,0 +1,6 @@
+[gd_scene load_steps=2 format=3 uid="uid://dtiuw54ss376d"]
+
+[ext_resource type="Script" path="res://behaviours/sampler_random.gd" id="1_geacn"]
+
+[node name="SamplerRandom" type="Node"]
+script = ExtResource("1_geacn")
diff --git a/behaviours/spawner_choice.gd b/behaviours/sampler_weighted.gd
similarity index 50%
rename from behaviours/spawner_choice.gd
rename to behaviours/sampler_weighted.gd
index 71def18..84bbc0d 100644
--- a/behaviours/spawner_choice.gd
+++ b/behaviours/sampler_weighted.gd
@@ -1,34 +1,29 @@
-extends Node
-class_name SpawnerChoice
+extends Sampler
+class_name SamplerWeighted
+
+
+## Sample a random reference from the array, considering the given weights.
-@export var spawners: Array[Spawner] = []
@export var weights: Array[int] = []
+func sample() -> Node:
+ var total = compute_total_weight()
+ if total == 0:
+ return null
+ var sampled = Random.rng.randi_range(0, total - 1)
+ var idx = -1
+ while sampled >= 0:
+ idx += 1
+ sampled -= weights[idx]
+ return possibilities[idx]
+
func compute_total_weight() -> int:
var total = 0
for weight in weights:
if weight < 0:
Log.e(self, "Weight with negative value detected.")
+ return 0
total += weight
return total
-
-func select_spawner() -> Spawner:
- var total = compute_total_weight()
- var sampled = Random.rng.randi_range(0, total - 1)
- var idx = -1
- while sampled >= 0:
- idx += 1
- sampled -= weights[idx]
- return spawners[idx]
-
-func spawn():
- select_spawner().spawn()
-
-
-func _ready():
- if len(spawners) != len(weights):
- Log.e(self, "Spawners and weights are different lengths.")
- if compute_total_weight() <= 0:
- Log.e(self, "Weight total is less or equal to 0.")
diff --git a/behaviours/sampler_weighted.tscn b/behaviours/sampler_weighted.tscn
new file mode 100644
index 0000000..fddbae7
--- /dev/null
+++ b/behaviours/sampler_weighted.tscn
@@ -0,0 +1,6 @@
+[gd_scene load_steps=2 format=3 uid="uid://d2ftjun7wdif0"]
+
+[ext_resource type="Script" path="res://behaviours/sampler_weighted.gd" id="1_hhnbk"]
+
+[node name="SamplerWeighted" type="Node"]
+script = ExtResource("1_hhnbk")
diff --git a/behaviours/skitter_from_mouse.gd b/behaviours/skitter_from_mouse.gd
deleted file mode 100644
index b7ee4b8..0000000
--- a/behaviours/skitter_from_mouse.gd
+++ /dev/null
@@ -1,68 +0,0 @@
-extends Node2D
-class_name SkitterFromMouse
-
-
-signal move(movement: Vector2)
-signal scared
-signal calmed
-
-
-@export_range(1, 500, 1) var speed: float = 300.0
-@export_range(0.1, 5, 0.1) var scare_secs: float = 0.2
-@export var directions: Array[Vector2] = []
-
-@onready var calm_timer: Timer = $"CalmTimer"
-@onready var scare_area: HoverDetector = $"ScareArea"
-
-
-enum State { CALM, SCARED }
-
-var state := State.CALM
-var direction := Vector2.ZERO
-
-
-func recheck():
- if scare_area.mouse_inside:
- scare()
- else:
- calm()
-
-func calm():
- state = State.CALM
- calmed.emit()
-
-func scare():
- state = State.SCARED
- # Pick a direction
- var idx := Random.rng.randi_range(0, len(directions) - 1)
- direction = directions[idx]
- # Start the timeout for calming down
- calm_timer.start(scare_secs)
- scared.emit()
-
-
-func _ready():
- if not directions:
- Log.w(self, "No directions defined, object won't skitter.")
-
-func _physics_process(delta: float) -> void:
- match state:
- State.SCARED:
- if len(directions) > 0:
- var movement: Vector2 = direction * delta * speed
- move.emit(movement)
-
-func _on_calm_timer_timeout() -> void:
- recheck()
-
-func _on_hover_detector_mouse_entered() -> void:
- scare()
-
-func _on_move(movement: Vector2) -> void:
- Log.p(self, "Moving by: %s" % movement)
-
-func _on_scared() -> void:
- Log.p(self, "Scared!")
-
-func _on_calmed() -> void:
- Log.p(self, "Calmed down.")
diff --git a/behaviours/skitter_from_mouse.tscn b/behaviours/skitter_from_mouse.tscn
deleted file mode 100644
index 8984d7a..0000000
--- a/behaviours/skitter_from_mouse.tscn
+++ /dev/null
@@ -1,18 +0,0 @@
-[gd_scene load_steps=3 format=3 uid="uid://c1wqgyakaultt"]
-
-[ext_resource type="Script" path="res://behaviours/skitter_from_mouse.gd" id="1_ftcf8"]
-[ext_resource type="PackedScene" uid="uid://cbg5kgwxusvxf" path="res://behaviours/hover_detector.tscn" id="2_cuaq0"]
-
-[node name="SkitterFromMouse" type="Node2D"]
-script = ExtResource("1_ftcf8")
-
-[node name="ScareArea" parent="." instance=ExtResource("2_cuaq0")]
-
-[node name="CalmTimer" type="Timer" parent="."]
-one_shot = true
-
-[connection signal="calmed" from="." to="." method="_on_calmed"]
-[connection signal="move" from="." to="." method="_on_move"]
-[connection signal="scared" from="." to="." method="_on_scared"]
-[connection signal="mouse_entered" from="ScareArea" to="." method="_on_hover_detector_mouse_entered"]
-[connection signal="timeout" from="CalmTimer" to="." method="_on_calm_timer_timeout"]
diff --git a/behaviours/spawner.gd b/behaviours/spawner.gd
index b1c9d6e..fbf5d8a 100644
--- a/behaviours/spawner.gd
+++ b/behaviours/spawner.gd
@@ -1,19 +1,37 @@
+@icon("res://behaviours/spawner.svg")
extends Node2D
class_name Spawner
+
+## Emitted when a new scene is spawned.
signal spawned(entity: Node2D)
-@export var scene: PackedScene
-@export var parent: Node2D
+## Emitted when the [field blocking_tracker] prevents something from spawning.
+signal spawn_blocked
+
+## The scene to spawn.
+@export var scene: PackedScene
+
+## Where the scene should be parented to in the tree.
+@export var target: Node2D
+
+## If set, requires the tracker to not be tracking anything before spawning a scene.
+@export var blocking_tracker: Tracker
+
+
+## Spawn [field scene] at [field target] and the position of this node.
func spawn():
+ if blocking_tracker != null:
+ if not blocking_tracker.tracking.is_empty():
+ spawn_blocked.emit()
+ return # Perhaps enqueue the spawn?
+ if not target:
+ target = MainGame.get_via_group(self).default_spawn_parent
+ if not target:
+ target = self
var entity = scene.instantiate()
entity.global_scale = global_scale
entity.global_position = global_position
entity.global_rotation = global_rotation
- parent.add_child.call_deferred(entity) # Not sure why this is needed.
-
-func _ready():
- if parent == null:
- parent = MainGame.get_ancestor(self).get_node("SpawnedEntities")
-
+ target.add_child.call_deferred(entity) # Not sure why this is needed.
diff --git a/behaviours/spawner.svg b/behaviours/spawner.svg
new file mode 100644
index 0000000..1396658
--- /dev/null
+++ b/behaviours/spawner.svg
@@ -0,0 +1,47 @@
+
+
diff --git a/behaviours/spawner.svg.import b/behaviours/spawner.svg.import
new file mode 100644
index 0000000..85aa700
--- /dev/null
+++ b/behaviours/spawner.svg.import
@@ -0,0 +1,37 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://2okawpk7lh5j"
+path="res://.godot/imported/spawner.svg-02e649ce51fee431d04ebb532f1c81e8.ctex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://behaviours/spawner.svg"
+dest_files=["res://.godot/imported/spawner.svg-02e649ce51fee431d04ebb532f1c81e8.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1
+svg/scale=1.0
+editor/scale_with_editor_scale=false
+editor/convert_colors_with_editor_theme=false
diff --git a/behaviours/spawner_choice.tscn b/behaviours/spawner_choice.tscn
deleted file mode 100644
index b11a7b0..0000000
--- a/behaviours/spawner_choice.tscn
+++ /dev/null
@@ -1,6 +0,0 @@
-[gd_scene load_steps=2 format=3 uid="uid://cokdfsk6rgeup"]
-
-[ext_resource type="Script" path="res://behaviours/spawner_choice.gd" id="1_jkwdb"]
-
-[node name="SpawnerChoice" type="Node"]
-script = ExtResource("1_jkwdb")
diff --git a/behaviours/spawner_free.tscn b/behaviours/spawner_free.tscn
deleted file mode 100644
index 6459ce3..0000000
--- a/behaviours/spawner_free.tscn
+++ /dev/null
@@ -1,8 +0,0 @@
-[gd_scene load_steps=2 format=3 uid="uid://dv7ea2y0l46e"]
-
-[ext_resource type="Script" path="res://behaviours/spawner.gd" id="1_fa574"]
-
-[node name="SpawnerFree" type="Node2D"]
-script = ExtResource("1_fa574")
-
-[connection signal="tree_exiting" from="." to="." method="spawn"]
diff --git a/behaviours/target_picker.gd b/behaviours/target_picker.gd
new file mode 100644
index 0000000..0f4d041
--- /dev/null
+++ b/behaviours/target_picker.gd
@@ -0,0 +1,48 @@
+@icon("res://behaviours/target_picker.svg")
+extends Node
+class_name TargetPicker
+
+
+## Pick a random target at random from [field Tracker.tracked], then emit it via [signal target_changed].
+
+
+signal target_changed(new: Node2D, old: Node2D)
+
+
+@export var tracker: Tracker
+
+
+var target: Node2D:
+ get:
+ return target
+ set(value):
+ if target != value:
+ var old = target
+ target = value
+ target_changed.emit(target, old)
+
+
+func set_target(body: Node2D) -> void:
+ target = body
+
+func set_target_if_null(body: Node2D) -> void:
+ if target == null:
+ target = body
+
+func clear_target() -> void:
+ target = null
+
+func clear_if_target(body: Node2D) -> void:
+ if target == body:
+ clear_target()
+
+func sample_target() -> void:
+ target = Random.sample(tracker.tracking)
+
+func sample_target_if_null() -> void:
+ if target == null:
+ sample_target()
+
+
+func log_target() -> void:
+ pass # Replace with function body.
diff --git a/behaviours/target_picker.svg b/behaviours/target_picker.svg
new file mode 100644
index 0000000..d8fead7
--- /dev/null
+++ b/behaviours/target_picker.svg
@@ -0,0 +1,39 @@
+
+
diff --git a/behaviours/target_picker.svg.import b/behaviours/target_picker.svg.import
new file mode 100644
index 0000000..43feff3
--- /dev/null
+++ b/behaviours/target_picker.svg.import
@@ -0,0 +1,37 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://dd7uvjl416h2k"
+path="res://.godot/imported/target_picker.svg-d96365c33742930a50d2b51102fd20f0.ctex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://behaviours/target_picker.svg"
+dest_files=["res://.godot/imported/target_picker.svg-d96365c33742930a50d2b51102fd20f0.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1
+svg/scale=1.0
+editor/scale_with_editor_scale=false
+editor/convert_colors_with_editor_theme=false
diff --git a/behaviours/target_picker.tscn b/behaviours/target_picker.tscn
new file mode 100644
index 0000000..8056ebd
--- /dev/null
+++ b/behaviours/target_picker.tscn
@@ -0,0 +1,6 @@
+[gd_scene load_steps=2 format=3 uid="uid://dti7l0d40hhgt"]
+
+[ext_resource type="Script" path="res://behaviours/target_picker.gd" id="1_ldiw7"]
+
+[node name="TargetPicker" type="Node"]
+script = ExtResource("1_ldiw7")
diff --git a/behaviours/timer_stddev.gd b/behaviours/timer_stddev.gd
new file mode 100644
index 0000000..6a05b64
--- /dev/null
+++ b/behaviours/timer_stddev.gd
@@ -0,0 +1,19 @@
+extends Timer
+class_name TimerStddev
+
+
+## A [Timer] which randomizes its [field wait_time] at each timeout.
+
+
+@export_range(0, 10, 0.1, "or_greater") var mean_secs: float = 1.0
+@export var deviation: float = 1.0
+@export_range(0, 10, 0.1, "or_greater") var min_secs: float = 0.0
+@export_range(0, 10, 0.1, "or_greater") var max_secs: float = 2.0
+
+
+func randomize_wait_time() -> void:
+ wait_time = clampf(
+ min_secs,
+ Random.rng.randfn(mean_secs, deviation),
+ max_secs
+ )
diff --git a/behaviours/timer_stddev.tscn b/behaviours/timer_stddev.tscn
new file mode 100644
index 0000000..b124203
--- /dev/null
+++ b/behaviours/timer_stddev.tscn
@@ -0,0 +1,8 @@
+[gd_scene load_steps=2 format=3 uid="uid://g8t6dt0ye6n3"]
+
+[ext_resource type="Script" path="res://behaviours/timer_stddev.gd" id="1_rvemn"]
+
+[node name="TimerStddev" type="Timer"]
+script = ExtResource("1_rvemn")
+
+[connection signal="timeout" from="." to="." method="randomize_wait_time"]
diff --git a/behaviours/tracker.gd b/behaviours/tracker.gd
new file mode 100644
index 0000000..b2dfbf5
--- /dev/null
+++ b/behaviours/tracker.gd
@@ -0,0 +1,44 @@
+@icon("res://behaviours/tracker.svg")
+extends Area2D
+class_name Tracker
+
+## [Area2D]s tracking a certain subset of [Node2D]s.
+
+
+signal tracked(body: Node2D)
+signal untracked(body: Node2D)
+
+var tracking: Array = []
+
+
+## Start [field tracking] a [Node2D].
+##
+## Returns whether the body was added to the [field tracking] array.
+func track(body: Node2D) -> bool:
+ var act: bool = not body in tracking
+ if act:
+ tracking.push_back(body)
+ tracked.emit(body)
+ # Handle TrackerTracker
+ for tracker_tracker in body.find_children("*", "TrackerTracker", true, false):
+ tracker_tracker.track_if_detected(self)
+ return act
+
+## Stop [field tracking] a [Node2D].
+##
+## Returns whether the body was removed from the [field tracking] array.
+func untrack(body: Node2D) -> bool:
+ var act: bool = body in tracking
+ if act:
+ tracking.erase(body)
+ untracked.emit(body)
+ # Handle TrackerTracker
+ for tracker_tracker in body.find_children("*", "TrackerTracker", true, false):
+ tracker_tracker.untrack(self)
+ return act
+
+func log_tracked(body: Node2D) -> void:
+ Log.p(self, "Tracking a new target: %s" % body)
+
+func log_untracked(body: Node2D) -> void:
+ Log.p(self, "Not tracking anymore target: %s" % body)
diff --git a/behaviours/tracker.svg b/behaviours/tracker.svg
new file mode 100644
index 0000000..327b1f2
--- /dev/null
+++ b/behaviours/tracker.svg
@@ -0,0 +1,39 @@
+
+
diff --git a/behaviours/tracker.svg.import b/behaviours/tracker.svg.import
new file mode 100644
index 0000000..32be8d3
--- /dev/null
+++ b/behaviours/tracker.svg.import
@@ -0,0 +1,37 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://b3myvaqud7w0p"
+path="res://.godot/imported/tracker.svg-98e9b55805c6d630e7da524610510efd.ctex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://behaviours/tracker.svg"
+dest_files=["res://.godot/imported/tracker.svg-98e9b55805c6d630e7da524610510efd.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1
+svg/scale=1.0
+editor/scale_with_editor_scale=false
+editor/convert_colors_with_editor_theme=false
diff --git a/behaviours/tracker.tscn b/behaviours/tracker.tscn
new file mode 100644
index 0000000..a2c6eec
--- /dev/null
+++ b/behaviours/tracker.tscn
@@ -0,0 +1,13 @@
+[gd_scene load_steps=2 format=3 uid="uid://8jkesanu4hrn"]
+
+[ext_resource type="Script" path="res://behaviours/tracker.gd" id="1_4joji"]
+
+[node name="Tracker" type="Area2D"]
+collision_layer = 0
+collision_mask = 56
+input_pickable = false
+monitorable = false
+script = ExtResource("1_4joji")
+
+[connection signal="body_entered" from="." to="." method="track"]
+[connection signal="body_exited" from="." to="." method="untrack"]
diff --git a/behaviours/tracker_edible.gd b/behaviours/tracker_edible.gd
new file mode 100644
index 0000000..810feb2
--- /dev/null
+++ b/behaviours/tracker_edible.gd
@@ -0,0 +1,15 @@
+extends Tracker
+class_name EdibleTracker
+
+## Keeps track of what [Edible]s are inside the area.
+
+
+@export var acceptable_diets: Array[StringName] = []
+
+
+func check_diet_then_track(body: Node2D) -> void:
+ var edibles: Array = body.find_children("*", "Edible", false, false)
+ for edible in edibles:
+ if edible.diet in acceptable_diets:
+ track(body)
+ break
diff --git a/behaviours/tracker_edible.tscn b/behaviours/tracker_edible.tscn
new file mode 100644
index 0000000..f9eb935
--- /dev/null
+++ b/behaviours/tracker_edible.tscn
@@ -0,0 +1,13 @@
+[gd_scene load_steps=2 format=3 uid="uid://ctpn4hvkhxoi3"]
+
+[ext_resource type="Script" path="res://behaviours/tracker_edible.gd" id="1_vmdw6"]
+
+[node name="TrackerEdible" type="Area2D"]
+collision_layer = 0
+collision_mask = 56
+input_pickable = false
+monitorable = false
+script = ExtResource("1_vmdw6")
+
+[connection signal="body_entered" from="." to="." method="check_diet_then_track"]
+[connection signal="body_exited" from="." to="." method="untrack"]
diff --git a/behaviours/tracker_tracker.gd b/behaviours/tracker_tracker.gd
new file mode 100644
index 0000000..b7940ad
--- /dev/null
+++ b/behaviours/tracker_tracker.gd
@@ -0,0 +1,24 @@
+extends Tracker
+class_name TrackerTracker
+
+## Tracks [Tracker]s tracking the parent.
+
+
+## Start [field tracking] a [Node2D] if it overlaps this [Area2D].
+##
+## Returns whether the body was added to the [field tracking] array.
+func track_if_detected(body: Node2D) -> bool:
+ if overlaps_body(body):
+ return track(body)
+ return false
+
+## Start [field tracking] a [Node2D] if it has a [Tracker] tracking this node or one of its ancestors.
+##
+## Returns whether the body was added to the [field tracking] array.
+func track_if_tracked(body: Node2D) -> bool:
+ var act: bool = false
+ for tracker in body.find_children("*", "Tracker", true, false):
+ for ancestor in Traversal.get_ancestors(self): # Make more efficient, perhaps?
+ if ancestor in tracker.tracking:
+ act = track(body) or act
+ return act
diff --git a/behaviours/tracker_tracker.tscn b/behaviours/tracker_tracker.tscn
new file mode 100644
index 0000000..e6763aa
--- /dev/null
+++ b/behaviours/tracker_tracker.tscn
@@ -0,0 +1,13 @@
+[gd_scene load_steps=2 format=3 uid="uid://c5pyp5hvthdof"]
+
+[ext_resource type="Script" path="res://behaviours/tracker_tracker.gd" id="1_7b21r"]
+
+[node name="TrackerTracker" type="Area2D"]
+collision_layer = 0
+collision_mask = 24
+input_pickable = false
+monitorable = false
+script = ExtResource("1_7b21r")
+
+[connection signal="body_entered" from="." to="." method="track_if_tracked"]
+[connection signal="body_exited" from="." to="." method="untrack"]
diff --git a/entities/drop.wav b/entities/drop.wav
deleted file mode 100644
index 2dbb33c..0000000
--- a/entities/drop.wav
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:39d8e006f4e8c678841a95097425c2452545a19946f40fdf917ce3601baa0d48
-size 359148
diff --git a/entities/drop.wav.import b/entities/drop.wav.import
deleted file mode 100644
index 08d956e..0000000
--- a/entities/drop.wav.import
+++ /dev/null
@@ -1,24 +0,0 @@
-[remap]
-
-importer="wav"
-type="AudioStreamWAV"
-uid="uid://buxgivpkh8dyl"
-path="res://.godot/imported/drop.wav-e321e3ff0b5883beef3e60642ca137ca.sample"
-
-[deps]
-
-source_file="res://entities/drop.wav"
-dest_files=["res://.godot/imported/drop.wav-e321e3ff0b5883beef3e60642ca137ca.sample"]
-
-[params]
-
-force/8_bit=false
-force/mono=false
-force/max_rate=false
-force/max_rate_hz=44100
-edit/trim=false
-edit/normalize=false
-edit/loop_mode=0
-edit/loop_begin=0
-edit/loop_end=-1
-compress/mode=0
diff --git a/entities/fall.ogg b/entities/fall.ogg
new file mode 100644
index 0000000..d0e149b
--- /dev/null
+++ b/entities/fall.ogg
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:2ceb2d1acdd2f606bc90bc5b578deec7f8987cc20a23b9e990c515be1dcc4f70
+size 10708
diff --git a/entities/fall.ogg.import b/entities/fall.ogg.import
new file mode 100644
index 0000000..6caf55e
--- /dev/null
+++ b/entities/fall.ogg.import
@@ -0,0 +1,19 @@
+[remap]
+
+importer="oggvorbisstr"
+type="AudioStreamOggVorbis"
+uid="uid://cwsg776c11xfc"
+path="res://.godot/imported/fall.ogg-ba2036bd4382e626c27cc3d1d5eb69f1.oggvorbisstr"
+
+[deps]
+
+source_file="res://entities/fall.ogg"
+dest_files=["res://.godot/imported/fall.ogg-ba2036bd4382e626c27cc3d1d5eb69f1.oggvorbisstr"]
+
+[params]
+
+loop=false
+loop_offset=0
+bpm=0
+beat_count=0
+bar_beats=4
diff --git a/entities/gold.gd b/entities/gold.gd
index c184a37..9edb2dd 100644
--- a/entities/gold.gd
+++ b/entities/gold.gd
@@ -2,18 +2,23 @@ extends Node2D
class_name Gold
-@export var value: int = 1
+@onready var game: MainGame = MainGame.get_via_group(self)
+@onready var move_towards: MoveTowards = %"MoveTowards"
+@onready var collect_sound_spawner: Spawner = %"CollectSoundSpawner"
+@onready var collectible: Collectible = %"Collectible"
+
+
+func magnetize(cursor: Cursor) -> void:
+ move_towards.target = cursor
+
+func demagnetize() -> void:
+ move_towards.target = null
+
+func collect() -> void:
+ collectible.apply()
+ collect_sound_spawner.spawn()
+ queue_free()
func _on_move(movement: Vector2) -> void:
position += movement
-
-func _on_collected(tag: StringName) -> void:
- var game = MainGame.get_ancestor(self)
-
- # TODO: Perhaps use a dictionary in game to store multiple currencies?
- match tag:
- &"Gold":
- game.gold_counter.increase(value)
-
- queue_free()
diff --git a/entities/gold.tscn b/entities/gold.tscn
index 2a86cd3..44584a3 100644
--- a/entities/gold.tscn
+++ b/entities/gold.tscn
@@ -1,29 +1,50 @@
-[gd_scene load_steps=7 format=3 uid="uid://uoxwjpmgg27a"]
+[gd_scene load_steps=10 format=3 uid="uid://uoxwjpmgg27a"]
[ext_resource type="Script" path="res://entities/gold.gd" id="1_lbls1"]
-[ext_resource type="PackedScene" uid="uid://bvrxvrjlo5130" path="res://behaviours/move_towards_mouse.tscn" id="2_lso1v"]
+[ext_resource type="PackedScene" uid="uid://dj72yshd25ucx" path="res://behaviours/collectible.tscn" id="2_j75yq"]
[ext_resource type="Texture2D" uid="uid://bfl0tkg85cvb8" path="res://entities/gold.png" id="2_tt3v6"]
-[ext_resource type="PackedScene" uid="uid://dj72yshd25ucx" path="res://behaviours/collectable.tscn" id="3_q0bno"]
-[ext_resource type="PackedScene" uid="uid://dv7ea2y0l46e" path="res://behaviours/spawner_free.tscn" id="5_pbaso"]
+[ext_resource type="PackedScene" uid="uid://cbg5kgwxusvxf" path="res://behaviours/cursor_detector.tscn" id="3_ne3sj"]
+[ext_resource type="PackedScene" uid="uid://cml7rqvyfuagx" path="res://behaviours/move_towards.tscn" id="5_bcbgf"]
+[ext_resource type="PackedScene" uid="uid://tx1qi6ahlxjp" path="res://behaviours/spawner.tscn" id="5_t7ey8"]
[ext_resource type="PackedScene" uid="uid://eqg6snsgn1kh" path="res://players/gold_pickup_player.tscn" id="6_eoeje"]
+[sub_resource type="CircleShape2D" id="CircleShape2D_w1h35"]
+radius = 64.0
+
+[sub_resource type="CircleShape2D" id="CircleShape2D_jm7yp"]
+
[node name="Gold" type="Node2D"]
script = ExtResource("1_lbls1")
+[node name="Collectible" parent="." instance=ExtResource("2_j75yq")]
+unique_name_in_owner = true
+kind = &"Gold"
+
[node name="Sprite" type="Sprite2D" parent="."]
scale = Vector2(2, 2)
texture = ExtResource("2_tt3v6")
-[node name="MoveTowardsMouse" parent="." instance=ExtResource("2_lso1v")]
-scale = Vector2(8, 8)
-speed = 555.0
+[node name="MagnetizeArea" parent="." instance=ExtResource("3_ne3sj")]
-[node name="Collectable" parent="." instance=ExtResource("3_q0bno")]
-scale = Vector2(0.6, 0.6)
-tag = &"Gold"
+[node name="Shape" type="CollisionShape2D" parent="MagnetizeArea"]
+shape = SubResource("CircleShape2D_w1h35")
+debug_color = Color(0.337255, 0.611765, 1, 0)
-[node name="SpawnerFree" parent="." instance=ExtResource("5_pbaso")]
+[node name="CollectArea" parent="." instance=ExtResource("3_ne3sj")]
+
+[node name="Shape" type="CollisionShape2D" parent="CollectArea"]
+shape = SubResource("CircleShape2D_jm7yp")
+debug_color = Color(0, 0.388235, 0.815686, 0.219608)
+
+[node name="MoveTowards" parent="." instance=ExtResource("5_bcbgf")]
+unique_name_in_owner = true
+speed = 184.0
+
+[node name="CollectSoundSpawner" parent="." instance=ExtResource("5_t7ey8")]
+unique_name_in_owner = true
+scale = Vector2(1.66667, 1.66667)
scene = ExtResource("6_eoeje")
-[connection signal="move" from="MoveTowardsMouse" to="." method="_on_move"]
-[connection signal="collected" from="Collectable" to="." method="_on_collected"]
+[connection signal="cursor_entered" from="MagnetizeArea" to="." method="magnetize"]
+[connection signal="cursor_entered" from="CollectArea" to="." method="collect" unbinds=1]
+[connection signal="move" from="MoveTowards" to="." method="_on_move"]
diff --git a/entities/imp.gd b/entities/imp.gd
index bbbd025..b5fb24e 100644
--- a/entities/imp.gd
+++ b/entities/imp.gd
@@ -1,25 +1,26 @@
extends CharacterBody2D
class_name Imp
-@export var skull_chance: float = 0.2
-@onready var skull_spawner: Spawner = $"SkullSpawner"
@onready var sprite: SpriteLeftRight = $"Sprite"
-@onready var draggable: Draggable = $"Draggable"
+@onready var eater: Eater = $"Eater"
-func _on_eat_target_eaten(target: Edible):
- target.queue_free()
- if Random.rng.randf() < skull_chance:
- skull_spawner.spawn()
+func _on_move(movement: Vector2):
+ move_and_collide(movement)
+ sprite.handle_move(movement)
+func _on_eater_eaten(edible: Edible) -> void:
+ edible.get_parent().queue_free()
-func _on_draggable_move(movement:Vector2):
- if draggable.being_dragged:
- move_and_collide(movement)
- sprite.handle_move(movement)
+func _on_dragged(_cursor: Cursor) -> void:
+ collision_layer = 16
+ collision_mask = 18
+ z_index = 1
+ eater.collision_mask = 16
-func _on_move(movement:Vector2):
- if not draggable.being_dragged:
- move_and_collide(movement)
- sprite.handle_move(movement)
+func _on_fallen() -> void:
+ collision_layer = 8
+ collision_mask = 14
+ z_index = 0
+ eater.collision_mask = 8
diff --git a/entities/imp.tscn b/entities/imp.tscn
index fdacd18..e58fc3e 100644
--- a/entities/imp.tscn
+++ b/entities/imp.tscn
@@ -1,20 +1,41 @@
-[gd_scene load_steps=10 format=3 uid="uid://4d3ksr3171x4"]
+[gd_scene load_steps=24 format=3 uid="uid://4d3ksr3171x4"]
[ext_resource type="Script" path="res://entities/imp.gd" id="1_dixpc"]
[ext_resource type="PackedScene" uid="uid://bxbjfev0lhwws" path="res://behaviours/sprite_left_right.tscn" id="2_eqcdi"]
-[ext_resource type="PackedScene" uid="uid://dijcjahkddudv" path="res://behaviours/draggable.tscn" id="3_4528r"]
-[ext_resource type="PackedScene" uid="uid://b7bdlh5akhi8s" path="res://behaviours/eat_target.tscn" id="3_iybf3"]
[ext_resource type="Texture2D" uid="uid://crhwsob76ieya" path="res://entities/imp_left.png" id="3_qda0k"]
[ext_resource type="Texture2D" uid="uid://bubehid53q8h1" path="res://entities/imp_right.png" id="4_0sckn"]
-[ext_resource type="PackedScene" path="res://behaviours/spawner.tscn" id="4_d8lgm"]
+[ext_resource type="PackedScene" uid="uid://tx1qi6ahlxjp" path="res://behaviours/spawner.tscn" id="4_d8lgm"]
[ext_resource type="PackedScene" uid="uid://uoxwjpmgg27a" path="res://entities/gold.tscn" id="5_yrfoq"]
+[ext_resource type="PackedScene" uid="uid://djcwis8ycrq85" path="res://behaviours/sampler_priority.tscn" id="7_ech8d"]
+[ext_resource type="PackedScene" uid="uid://dk1ipq7dhkhf3" path="res://behaviours/move_straight.tscn" id="8_ffcw0"]
+[ext_resource type="PackedScene" uid="uid://cm67ko1k6kn4u" path="res://behaviours/priority.tscn" id="9_2wb1b"]
+[ext_resource type="PackedScene" uid="uid://g8t6dt0ye6n3" path="res://behaviours/timer_stddev.tscn" id="10_phvea"]
+[ext_resource type="PackedScene" uid="uid://cml7rqvyfuagx" path="res://behaviours/move_towards.tscn" id="11_4ra22"]
+[ext_resource type="PackedScene" uid="uid://ctpn4hvkhxoi3" path="res://behaviours/tracker_edible.tscn" id="12_dr2oe"]
+[ext_resource type="PackedScene" uid="uid://dti7l0d40hhgt" path="res://behaviours/target_picker.tscn" id="13_mwxuf"]
+[ext_resource type="PackedScene" uid="uid://rx24bppccih7" path="res://behaviours/move_physics.tscn" id="14_p3w0g"]
+[ext_resource type="PackedScene" uid="uid://jg7qkbswgqjc" path="res://behaviours/eater.tscn" id="14_w2h8x"]
+[ext_resource type="PackedScene" uid="uid://dijcjahkddudv" path="res://behaviours/draggable.tscn" id="15_otrbh"]
+[ext_resource type="AudioStream" uid="uid://d0feiq5s6fnux" path="res://entities/imp_drag.wav" id="16_0frai"]
+[ext_resource type="AudioStream" uid="uid://cwsg776c11xfc" path="res://entities/fall.ogg" id="17_lib0h"]
+[ext_resource type="AudioStream" uid="uid://c1yuksnjdd6g2" path="res://entities/imp_eat.ogg" id="19_7la6c"]
[sub_resource type="CircleShape2D" id="CircleShape2D_ide4n"]
-radius = 8.0
+radius = 32.0
+
+[sub_resource type="CircleShape2D" id="CircleShape2D_1bmhf"]
+radius = 256.0
+
+[sub_resource type="CircleShape2D" id="CircleShape2D_50iad"]
+radius = 32.0
+
+[sub_resource type="CircleShape2D" id="CircleShape2D_qhk1q"]
+radius = 40.0
[node name="Imp" type="CharacterBody2D"]
collision_layer = 8
collision_mask = 14
+motion_mode = 1
script = ExtResource("1_dixpc")
[node name="Sprite" parent="." instance=ExtResource("2_eqcdi")]
@@ -24,33 +45,103 @@ left_texture = ExtResource("3_qda0k")
right_texture = ExtResource("4_0sckn")
[node name="Shape" type="CollisionShape2D" parent="."]
-scale = Vector2(4, 4)
shape = SubResource("CircleShape2D_ide4n")
-[node name="Draggable" parent="." instance=ExtResource("3_4528r")]
-scale = Vector2(4, 4)
-
-[node name="DragSound" type="AudioStreamPlayer2D" parent="Draggable"]
-scale = Vector2(0.5, 0.5)
-
-[node name="DropSound" type="AudioStreamPlayer2D" parent="Draggable"]
-scale = Vector2(0.5, 0.5)
-
-[node name="EatTarget" parent="." instance=ExtResource("3_iybf3")]
-scale = Vector2(2, 2)
-tag = &"Sheep"
-
-[node name="SkullSpawner" parent="." instance=ExtResource("4_d8lgm")]
+[node name="GoldSpawner" parent="." instance=ExtResource("4_d8lgm")]
scene = ExtResource("5_yrfoq")
-[node name="Spawner" parent="." instance=ExtResource("4_d8lgm")]
-scene = ExtResource("5_yrfoq")
-
-[node name="Timer" type="Timer" parent="Spawner"]
-wait_time = 0.8
+[node name="TimerStddev" parent="GoldSpawner" instance=ExtResource("10_phvea")]
autostart = true
+mean_secs = 5.0
+deviation = 4.0
+min_secs = 1.0
+max_secs = 9.0
-[connection signal="move" from="Draggable" to="." method="_on_draggable_move"]
-[connection signal="eaten" from="EatTarget" to="." method="_on_eat_target_eaten"]
-[connection signal="move" from="EatTarget" to="." method="_on_move"]
-[connection signal="timeout" from="Spawner/Timer" to="Spawner" method="spawn"]
+[node name="MovementSampler" parent="." node_paths=PackedStringArray("possibilities") instance=ExtResource("7_ech8d")]
+possibilities = [NodePath("../MovementWander/WanderPriority"), NodePath("../MovementHunt/HuntPriority"), NodePath("../MovementDrag/DragPriority")]
+
+[node name="MovementWander" parent="." instance=ExtResource("8_ffcw0")]
+speed = 25.0
+enabled = false
+
+[node name="WanderPriority" parent="MovementWander" instance=ExtResource("9_2wb1b")]
+default_priority = 10
+alternative_priority = 10
+
+[node name="ChangeDirectionTimer" parent="MovementWander" instance=ExtResource("10_phvea")]
+autostart = true
+mean_secs = 2.0
+deviation = 2.0
+min_secs = 0.6
+max_secs = 3.0
+
+[node name="MovementHunt" parent="." instance=ExtResource("11_4ra22")]
+speed = 140.0
+enabled = false
+
+[node name="HuntPriority" parent="MovementHunt" instance=ExtResource("9_2wb1b")]
+alternative_priority = 40
+
+[node name="TrackerMeat" parent="MovementHunt" instance=ExtResource("12_dr2oe")]
+acceptable_diets = Array[StringName]([&"Meat"])
+
+[node name="Shape" type="CollisionShape2D" parent="MovementHunt/TrackerMeat"]
+shape = SubResource("CircleShape2D_1bmhf")
+debug_color = Color(1, 0.498039, 0, 0)
+
+[node name="TargetPicker" parent="MovementHunt/TrackerMeat" node_paths=PackedStringArray("tracker") instance=ExtResource("13_mwxuf")]
+tracker = NodePath("..")
+
+[node name="MovementDrag" parent="." instance=ExtResource("14_p3w0g")]
+enabled = false
+
+[node name="DragPriority" parent="MovementDrag" instance=ExtResource("9_2wb1b")]
+alternative_priority = 50
+
+[node name="Draggable" parent="MovementDrag" instance=ExtResource("15_otrbh")]
+
+[node name="Shape" type="CollisionShape2D" parent="MovementDrag/Draggable"]
+shape = SubResource("CircleShape2D_50iad")
+debug_color = Color(1, 1, 1, 0)
+
+[node name="DragSound" type="AudioStreamPlayer2D" parent="MovementDrag"]
+stream = ExtResource("16_0frai")
+
+[node name="FallSound" type="AudioStreamPlayer2D" parent="MovementDrag"]
+stream = ExtResource("17_lib0h")
+
+[node name="Eater" parent="." instance=ExtResource("14_w2h8x")]
+acceptable_diets = Array[StringName]([&"Meat"])
+
+[node name="Shape" type="CollisionShape2D" parent="Eater"]
+shape = SubResource("CircleShape2D_qhk1q")
+debug_color = Color(1, 0, 0, 0)
+
+[node name="EatSound" type="AudioStreamPlayer2D" parent="Eater"]
+stream = ExtResource("19_7la6c")
+
+[connection signal="timeout" from="GoldSpawner/TimerStddev" to="GoldSpawner" method="spawn"]
+[connection signal="ready" from="MovementSampler" to="MovementSampler" method="enable"]
+[connection signal="changed_direction" from="MovementWander" to="MovementWander/WanderPriority" method="priority_conditional"]
+[connection signal="move" from="MovementWander" to="." method="_on_move"]
+[connection signal="priority_changed_no_args" from="MovementWander/WanderPriority" to="MovementSampler" method="enable"]
+[connection signal="timeout" from="MovementWander/ChangeDirectionTimer" to="MovementWander" method="randomize_direction"]
+[connection signal="changed_target" from="MovementHunt" to="MovementHunt/HuntPriority" method="priority_conditional"]
+[connection signal="move" from="MovementHunt" to="." method="_on_move"]
+[connection signal="priority_changed_no_args" from="MovementHunt/HuntPriority" to="MovementSampler" method="enable"]
+[connection signal="tracked" from="MovementHunt/TrackerMeat" to="MovementHunt/TrackerMeat/TargetPicker" method="sample_target_if_null" unbinds=1]
+[connection signal="untracked" from="MovementHunt/TrackerMeat" to="MovementHunt/TrackerMeat/TargetPicker" method="clear_if_target"]
+[connection signal="target_changed" from="MovementHunt/TrackerMeat/TargetPicker" to="MovementHunt" method="set_target" unbinds=1]
+[connection signal="target_changed" from="MovementHunt/TrackerMeat/TargetPicker" to="MovementHunt/TrackerMeat/TargetPicker" method="sample_target_if_null" unbinds=2]
+[connection signal="dragged" from="MovementDrag" to="." method="_on_dragged"]
+[connection signal="dragged" from="MovementDrag" to="MovementDrag/DragPriority" method="priority_alternative" unbinds=1]
+[connection signal="dragged" from="MovementDrag" to="MovementDrag/DragSound" method="play" unbinds=1]
+[connection signal="fallen" from="MovementDrag" to="." method="_on_fallen"]
+[connection signal="fallen" from="MovementDrag" to="MovementDrag/DragPriority" method="priority_default"]
+[connection signal="fallen" from="MovementDrag" to="MovementDrag/FallSound" method="play"]
+[connection signal="move" from="MovementDrag" to="." method="_on_move"]
+[connection signal="priority_changed_no_args" from="MovementDrag/DragPriority" to="MovementSampler" method="enable"]
+[connection signal="dragged" from="MovementDrag/Draggable" to="MovementDrag" method="drag"]
+[connection signal="dropped" from="MovementDrag/Draggable" to="MovementDrag" method="drop"]
+[connection signal="eaten" from="Eater" to="." method="_on_eater_eaten"]
+[connection signal="eaten" from="Eater" to="Eater/EatSound" method="play" unbinds=1]
diff --git a/temp/tank.wav b/entities/imp_drag.wav
similarity index 100%
rename from temp/tank.wav
rename to entities/imp_drag.wav
diff --git a/temp/tank.wav.import b/entities/imp_drag.wav.import
similarity index 56%
rename from temp/tank.wav.import
rename to entities/imp_drag.wav.import
index 824282a..8b66524 100644
--- a/temp/tank.wav.import
+++ b/entities/imp_drag.wav.import
@@ -3,12 +3,12 @@
importer="wav"
type="AudioStreamWAV"
uid="uid://d0feiq5s6fnux"
-path="res://.godot/imported/tank.wav-76da0daecf3b365c21fcd97289993799.sample"
+path="res://.godot/imported/imp_drag.wav-e4ed42c6f5f4ccfe6d180bc00d8af7df.sample"
[deps]
-source_file="res://temp/tank.wav"
-dest_files=["res://.godot/imported/tank.wav-76da0daecf3b365c21fcd97289993799.sample"]
+source_file="res://entities/imp_drag.wav"
+dest_files=["res://.godot/imported/imp_drag.wav-e4ed42c6f5f4ccfe6d180bc00d8af7df.sample"]
[params]
diff --git a/entities/imp_eat.ogg b/entities/imp_eat.ogg
new file mode 100644
index 0000000..63f7d70
--- /dev/null
+++ b/entities/imp_eat.ogg
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:7804f60b616a01fa2dc07371af00f1b15f726bd0fcb5be456b39c39b81497ea3
+size 16127
diff --git a/entities/imp_eat.ogg.import b/entities/imp_eat.ogg.import
new file mode 100644
index 0000000..362c0af
--- /dev/null
+++ b/entities/imp_eat.ogg.import
@@ -0,0 +1,19 @@
+[remap]
+
+importer="oggvorbisstr"
+type="AudioStreamOggVorbis"
+uid="uid://c1yuksnjdd6g2"
+path="res://.godot/imported/imp_eat.ogg-8244e5ac229d57fa0fbf148a2e9862db.oggvorbisstr"
+
+[deps]
+
+source_file="res://entities/imp_eat.ogg"
+dest_files=["res://.godot/imported/imp_eat.ogg-8244e5ac229d57fa0fbf148a2e9862db.oggvorbisstr"]
+
+[params]
+
+loop=false
+loop_offset=0
+bpm=0
+beat_count=0
+bar_beats=4
diff --git a/entities/monocle.gd b/entities/monocle.gd
new file mode 100644
index 0000000..c7d507f
--- /dev/null
+++ b/entities/monocle.gd
@@ -0,0 +1,16 @@
+extends CharacterBody2D
+class_name Monocle
+
+
+func _on_move(movement: Vector2) -> void:
+ move_and_collide(movement)
+
+func _on_dragged(_cursor: Cursor) -> void:
+ collision_layer = 16
+ collision_mask = 18
+ z_index = 1
+
+func _on_fallen() -> void:
+ collision_layer = 8
+ collision_mask = 14
+ z_index = 0
diff --git a/temp/pickup_monocle.png b/entities/monocle.png
similarity index 100%
rename from temp/pickup_monocle.png
rename to entities/monocle.png
diff --git a/temp/pickup_monocle.png.import b/entities/monocle.png.import
similarity index 71%
rename from temp/pickup_monocle.png.import
rename to entities/monocle.png.import
index f945286..6588bf2 100644
--- a/temp/pickup_monocle.png.import
+++ b/entities/monocle.png.import
@@ -3,15 +3,15 @@
importer="texture"
type="CompressedTexture2D"
uid="uid://d3tb6ypb36v8e"
-path="res://.godot/imported/pickup_monocle.png-7a9e8cda4415a7ebfbddb870020ff730.ctex"
+path="res://.godot/imported/monocle.png-2e39f2ebd2473082b74edcdb99c2e85d.ctex"
metadata={
"vram_texture": false
}
[deps]
-source_file="res://temp/pickup_monocle.png"
-dest_files=["res://.godot/imported/pickup_monocle.png-7a9e8cda4415a7ebfbddb870020ff730.ctex"]
+source_file="res://entities/monocle.png"
+dest_files=["res://.godot/imported/monocle.png-2e39f2ebd2473082b74edcdb99c2e85d.ctex"]
[params]
diff --git a/entities/monocle.tscn b/entities/monocle.tscn
new file mode 100644
index 0000000..8eb8379
--- /dev/null
+++ b/entities/monocle.tscn
@@ -0,0 +1,49 @@
+[gd_scene load_steps=9 format=3 uid="uid://b04xhv32ypi42"]
+
+[ext_resource type="Script" path="res://entities/monocle.gd" id="1_ehpfj"]
+[ext_resource type="Texture2D" uid="uid://d3tb6ypb36v8e" path="res://entities/monocle.png" id="1_omrit"]
+[ext_resource type="PackedScene" uid="uid://rx24bppccih7" path="res://behaviours/move_physics.tscn" id="2_jgnsw"]
+[ext_resource type="PackedScene" uid="uid://dijcjahkddudv" path="res://behaviours/draggable.tscn" id="3_e0ni5"]
+[ext_resource type="AudioStream" uid="uid://dgd1ldpffk6ql" path="res://entities/monocle_drag.wav" id="5_bs8m7"]
+[ext_resource type="AudioStream" uid="uid://cwsg776c11xfc" path="res://entities/fall.ogg" id="5_grwug"]
+
+[sub_resource type="CircleShape2D" id="CircleShape2D_o7chm"]
+radius = 12.0
+
+[sub_resource type="CircleShape2D" id="CircleShape2D_juisb"]
+radius = 12.0
+
+[node name="Monocle" type="CharacterBody2D"]
+collision_layer = 8
+collision_mask = 14
+motion_mode = 1
+script = ExtResource("1_ehpfj")
+
+[node name="Sprite" type="Sprite2D" parent="."]
+scale = Vector2(2, 2)
+texture = ExtResource("1_omrit")
+
+[node name="Shape" type="CollisionShape2D" parent="."]
+shape = SubResource("CircleShape2D_o7chm")
+
+[node name="MovementDrag" parent="." instance=ExtResource("2_jgnsw")]
+
+[node name="Draggable" parent="MovementDrag" instance=ExtResource("3_e0ni5")]
+
+[node name="Shape" type="CollisionShape2D" parent="MovementDrag/Draggable"]
+shape = SubResource("CircleShape2D_juisb")
+debug_color = Color(1, 1, 1, 0)
+
+[node name="DragSound" type="AudioStreamPlayer2D" parent="MovementDrag"]
+stream = ExtResource("5_bs8m7")
+
+[node name="FallSound" type="AudioStreamPlayer2D" parent="MovementDrag"]
+stream = ExtResource("5_grwug")
+
+[connection signal="dragged" from="MovementDrag" to="." method="_on_dragged"]
+[connection signal="dragged" from="MovementDrag" to="MovementDrag/DragSound" method="play" unbinds=1]
+[connection signal="fallen" from="MovementDrag" to="." method="_on_fallen"]
+[connection signal="fallen" from="MovementDrag" to="MovementDrag/FallSound" method="play"]
+[connection signal="move" from="MovementDrag" to="." method="_on_move"]
+[connection signal="dragged" from="MovementDrag/Draggable" to="MovementDrag" method="drag"]
+[connection signal="dropped" from="MovementDrag/Draggable" to="MovementDrag" method="drop"]
diff --git a/temp/pop.wav b/entities/monocle_drag.wav
similarity index 100%
rename from temp/pop.wav
rename to entities/monocle_drag.wav
diff --git a/temp/pop.wav.import b/entities/monocle_drag.wav.import
similarity index 55%
rename from temp/pop.wav.import
rename to entities/monocle_drag.wav.import
index 82ce6ca..6e59e39 100644
--- a/temp/pop.wav.import
+++ b/entities/monocle_drag.wav.import
@@ -3,12 +3,12 @@
importer="wav"
type="AudioStreamWAV"
uid="uid://dgd1ldpffk6ql"
-path="res://.godot/imported/pop.wav-5c8ab1a460889e6b7e24366eae5d4a3a.sample"
+path="res://.godot/imported/monocle_drag.wav-d899e772e1792f41cd5a6ddac30bd2f6.sample"
[deps]
-source_file="res://temp/pop.wav"
-dest_files=["res://.godot/imported/pop.wav-5c8ab1a460889e6b7e24366eae5d4a3a.sample"]
+source_file="res://entities/monocle_drag.wav"
+dest_files=["res://.godot/imported/monocle_drag.wav-d899e772e1792f41cd5a6ddac30bd2f6.sample"]
[params]
diff --git a/entities/sheep.gd b/entities/sheep.gd
index b38d4ea..e28982c 100644
--- a/entities/sheep.gd
+++ b/entities/sheep.gd
@@ -2,10 +2,7 @@ extends CharacterBody2D
class_name Sheep
-@onready var draggable: Draggable = $"Draggable"
@onready var sprite: SpriteLeftRight = $"Sprite"
-@onready var drag_sound: AudioStreamPlayer2D = $"Draggable/DragSound"
-@onready var drop_sound: AudioStreamPlayer2D = $"Draggable/DropSound"
@onready var animator: AnimationPlayer = $"Animator"
@@ -13,19 +10,15 @@ func _ready() -> void:
animator.play("RESET")
func _on_move(movement: Vector2) -> void:
- if not draggable.being_dragged:
- move_and_collide(movement)
- sprite.handle_move(movement)
+ move_and_collide(movement)
+ sprite.handle_move(movement)
-func _on_drag_move(movement: Vector2) -> void:
- if draggable.being_dragged:
- move_and_collide(movement)
- sprite.handle_move(movement)
+func _on_dragged(_cursor: Cursor) -> void:
+ collision_layer = 16
+ collision_mask = 18
+ z_index = 1
-func _on_draggable_dragged() -> void:
- drag_sound.play()
- animator.play("wobble")
-
-func _on_draggable_dropped() -> void:
- drop_sound.play()
- animator.play("RESET")
+func _on_fallen() -> void:
+ collision_layer = 8
+ collision_mask = 14
+ z_index = 0
diff --git a/entities/sheep.tscn b/entities/sheep.tscn
index 4ae08bb..b07e995 100644
--- a/entities/sheep.tscn
+++ b/entities/sheep.tscn
@@ -1,36 +1,26 @@
-[gd_scene load_steps=15 format=3 uid="uid://bc2bm8lbol18w"]
+[gd_scene load_steps=24 format=3 uid="uid://bc2bm8lbol18w"]
[ext_resource type="Script" path="res://entities/sheep.gd" id="1_4dmll"]
[ext_resource type="Texture2D" uid="uid://iljp5yn3ehfk" path="res://entities/sheep_left.png" id="2_t13f5"]
-[ext_resource type="PackedScene" uid="uid://bvrxvrjlo5130" path="res://behaviours/move_towards_mouse.tscn" id="2_tfd2i"]
[ext_resource type="PackedScene" uid="uid://bxbjfev0lhwws" path="res://behaviours/sprite_left_right.tscn" id="2_xbkrm"]
-[ext_resource type="PackedScene" uid="uid://dijcjahkddudv" path="res://behaviours/draggable.tscn" id="3_8ku7r"]
[ext_resource type="Texture2D" uid="uid://cxtmas4g0v6en" path="res://entities/sheep_right.png" id="4_5qoof"]
-[ext_resource type="AudioStream" uid="uid://buxgivpkh8dyl" path="res://entities/drop.wav" id="4_nxjnl"]
-[ext_resource type="AudioStream" uid="uid://bmfscpnugaejk" path="res://entities/sheep_drag.wav" id="4_oalqu"]
[ext_resource type="PackedScene" uid="uid://dfdr3e32lohq" path="res://behaviours/edible.tscn" id="6_3odsh"]
+[ext_resource type="PackedScene" uid="uid://djcwis8ycrq85" path="res://behaviours/sampler_priority.tscn" id="9_s5lod"]
+[ext_resource type="PackedScene" uid="uid://dk1ipq7dhkhf3" path="res://behaviours/move_straight.tscn" id="10_05kcd"]
+[ext_resource type="PackedScene" uid="uid://cm67ko1k6kn4u" path="res://behaviours/priority.tscn" id="11_0jlmk"]
+[ext_resource type="PackedScene" uid="uid://g8t6dt0ye6n3" path="res://behaviours/timer_stddev.tscn" id="12_c45uk"]
+[ext_resource type="PackedScene" uid="uid://cml7rqvyfuagx" path="res://behaviours/move_towards.tscn" id="12_x2g3x"]
+[ext_resource type="PackedScene" uid="uid://cbg5kgwxusvxf" path="res://behaviours/cursor_detector.tscn" id="13_5fkdr"]
+[ext_resource type="PackedScene" uid="uid://dti7l0d40hhgt" path="res://behaviours/target_picker.tscn" id="13_jf6em"]
+[ext_resource type="PackedScene" uid="uid://dijcjahkddudv" path="res://behaviours/draggable.tscn" id="14_0b1hs"]
+[ext_resource type="PackedScene" uid="uid://rx24bppccih7" path="res://behaviours/move_physics.tscn" id="14_3wojv"]
+[ext_resource type="PackedScene" uid="uid://c5pyp5hvthdof" path="res://behaviours/tracker_tracker.tscn" id="14_eqowb"]
+[ext_resource type="AudioStream" uid="uid://bmfscpnugaejk" path="res://entities/sheep_drag.wav" id="16_nswfl"]
+[ext_resource type="AudioStream" uid="uid://cwsg776c11xfc" path="res://entities/fall.ogg" id="17_8kst2"]
[sub_resource type="CircleShape2D" id="CircleShape2D_c5tcn"]
radius = 8.0
-[sub_resource type="Animation" id="Animation_lxieb"]
-resource_name = "wobble"
-length = 3.0
-loop_mode = 1
-step = 0.5
-tracks/0/type = "value"
-tracks/0/imported = false
-tracks/0/enabled = true
-tracks/0/path = NodePath("Sprite:rotation")
-tracks/0/interp = 2
-tracks/0/loop_wrap = true
-tracks/0/keys = {
-"times": PackedFloat32Array(0, 0.5, 1.5, 2, 3),
-"transitions": PackedFloat32Array(1, 1, 1, 1, 1),
-"update": 0,
-"values": [0.0, -0.261799, 0.0, 0.261799, 0.0]
-}
-
[sub_resource type="Animation" id="Animation_gokbg"]
length = 0.001
tracks/0/type = "value"
@@ -64,6 +54,24 @@ tracks/0/keys = {
"values": [Vector2(0, 0), Vector2(1, 1), Vector2(-1, -1), Vector2(-1, 0), Vector2(1, -1), Vector2(-1, 1), Vector2(1, 1), Vector2(1, 0), Vector2(-1, -1), Vector2(1, 0), Vector2(0, -1)]
}
+[sub_resource type="Animation" id="Animation_lxieb"]
+resource_name = "wobble"
+length = 3.0
+loop_mode = 1
+step = 0.5
+tracks/0/type = "value"
+tracks/0/imported = false
+tracks/0/enabled = true
+tracks/0/path = NodePath("Sprite:rotation")
+tracks/0/interp = 2
+tracks/0/loop_wrap = true
+tracks/0/keys = {
+"times": PackedFloat32Array(0, 0.5, 1.5, 2, 3),
+"transitions": PackedFloat32Array(1, 1, 1, 1, 1),
+"update": 0,
+"values": [0.0, -0.261799, 0.0, 0.261799, 0.0]
+}
+
[sub_resource type="AnimationLibrary" id="AnimationLibrary_6mutq"]
_data = {
"RESET": SubResource("Animation_gokbg"),
@@ -71,9 +79,13 @@ _data = {
"wobble": SubResource("Animation_lxieb")
}
+[sub_resource type="CircleShape2D" id="CircleShape2D_etpf6"]
+radius = 144.0
+
[node name="Sheep" type="CharacterBody2D"]
collision_layer = 8
collision_mask = 14
+motion_mode = 1
script = ExtResource("1_4dmll")
[node name="Sprite" parent="." instance=ExtResource("2_xbkrm")]
@@ -87,31 +99,124 @@ right_texture = ExtResource("4_5qoof")
scale = Vector2(3, 3)
shape = SubResource("CircleShape2D_c5tcn")
-[node name="MoveTowardsMouse" parent="." instance=ExtResource("2_tfd2i")]
-scale = Vector2(30, 30)
-speed = -30.0
-can_detach = true
-
-[node name="Draggable" parent="." instance=ExtResource("3_8ku7r")]
-scale = Vector2(3, 3)
-
-[node name="DragSound" type="AudioStreamPlayer2D" parent="Draggable"]
-scale = Vector2(0.5, 0.5)
-stream = ExtResource("4_oalqu")
-
-[node name="DropSound" type="AudioStreamPlayer2D" parent="Draggable"]
-scale = Vector2(0.5, 0.5)
-stream = ExtResource("4_nxjnl")
-
-[node name="Edible" parent="." instance=ExtResource("6_3odsh")]
-tag = &"Sheep"
-
[node name="Animator" type="AnimationPlayer" parent="."]
libraries = {
"": SubResource("AnimationLibrary_6mutq")
}
-[connection signal="move" from="MoveTowardsMouse" to="." method="_on_move"]
-[connection signal="dragged" from="Draggable" to="." method="_on_draggable_dragged"]
-[connection signal="dropped" from="Draggable" to="." method="_on_draggable_dropped"]
-[connection signal="move" from="Draggable" to="." method="_on_drag_move"]
+[node name="Edible" parent="." instance=ExtResource("6_3odsh")]
+diet = &"Meat"
+
+[node name="MovementSampler" parent="." node_paths=PackedStringArray("possibilities") instance=ExtResource("9_s5lod")]
+possibilities = [NodePath("../MovementIdle/IdlePriority"), NodePath("../MovementWander/WanderPriority"), NodePath("../MovementRunFromMouse/RunFromMousePriority"), NodePath("../MovementRunFromHunter/RunFromHunterPriority"), NodePath("../MovementDrag/DragPriority")]
+
+[node name="MovementIdle" parent="." instance=ExtResource("10_05kcd")]
+speed = 0.0
+enabled = false
+
+[node name="IdlePriority" parent="MovementIdle" instance=ExtResource("11_0jlmk")]
+alternative_priority = 0
+
+[node name="BoredTimer" parent="MovementIdle" instance=ExtResource("12_c45uk")]
+one_shot = true
+autostart = true
+mean_secs = 3.0
+min_secs = 1.0
+max_secs = 5.0
+
+[node name="MovementWander" parent="." instance=ExtResource("10_05kcd")]
+speed = 33.0
+enabled = false
+
+[node name="WanderPriority" parent="MovementWander" instance=ExtResource("11_0jlmk")]
+alternative_priority = 20
+
+[node name="TiredTimer" parent="MovementWander" instance=ExtResource("12_c45uk")]
+one_shot = true
+min_secs = 0.3
+max_secs = 1.5
+
+[node name="MovementRunFromMouse" parent="." instance=ExtResource("12_x2g3x")]
+speed = -66.0
+enabled = false
+
+[node name="RunFromMousePriority" parent="MovementRunFromMouse" instance=ExtResource("11_0jlmk")]
+alternative_priority = 30
+
+[node name="CursorSense" parent="MovementRunFromMouse" instance=ExtResource("13_5fkdr")]
+
+[node name="Shape" type="CollisionShape2D" parent="MovementRunFromMouse/CursorSense"]
+shape = SubResource("CircleShape2D_etpf6")
+debug_color = Color(1, 1, 0, 0)
+
+[node name="MovementRunFromHunter" parent="." instance=ExtResource("12_x2g3x")]
+speed = -66.0
+enabled = false
+
+[node name="RunFromHunterPriority" parent="MovementRunFromHunter" instance=ExtResource("11_0jlmk")]
+alternative_priority = 40
+
+[node name="HunterSense" parent="MovementRunFromHunter" instance=ExtResource("14_eqowb")]
+
+[node name="Shape" type="CollisionShape2D" parent="MovementRunFromHunter/HunterSense"]
+shape = SubResource("CircleShape2D_etpf6")
+debug_color = Color(1, 1, 0, 0)
+
+[node name="TargetPicker" parent="MovementRunFromHunter/HunterSense" node_paths=PackedStringArray("tracker") instance=ExtResource("13_jf6em")]
+tracker = NodePath("..")
+
+[node name="MovementDrag" parent="." instance=ExtResource("14_3wojv")]
+enabled = false
+
+[node name="DragPriority" parent="MovementDrag" instance=ExtResource("11_0jlmk")]
+alternative_priority = 50
+
+[node name="Draggable" parent="MovementDrag" instance=ExtResource("14_0b1hs")]
+
+[node name="Shape" type="CollisionShape2D" parent="MovementDrag/Draggable"]
+scale = Vector2(3, 3)
+shape = SubResource("CircleShape2D_c5tcn")
+debug_color = Color(1, 1, 1, 0)
+
+[node name="DragSound" type="AudioStreamPlayer2D" parent="MovementDrag"]
+stream = ExtResource("16_nswfl")
+
+[node name="FallSound" type="AudioStreamPlayer2D" parent="MovementDrag"]
+stream = ExtResource("17_8kst2")
+
+[connection signal="ready" from="MovementSampler" to="MovementSampler" method="enable"]
+[connection signal="move" from="MovementIdle" to="." method="_on_move"]
+[connection signal="move_disabled" from="MovementIdle" to="MovementIdle/BoredTimer" method="stop"]
+[connection signal="move_enabled" from="MovementIdle" to="MovementIdle/BoredTimer" method="start"]
+[connection signal="priority_changed_no_args" from="MovementIdle/IdlePriority" to="MovementSampler" method="enable"]
+[connection signal="timeout" from="MovementIdle/BoredTimer" to="MovementWander" method="randomize_direction"]
+[connection signal="changed_direction" from="MovementWander" to="MovementWander/WanderPriority" method="priority_conditional"]
+[connection signal="move" from="MovementWander" to="." method="_on_move"]
+[connection signal="move_disabled" from="MovementWander" to="MovementWander/TiredTimer" method="stop"]
+[connection signal="move_enabled" from="MovementWander" to="MovementWander/TiredTimer" method="start"]
+[connection signal="priority_changed_no_args" from="MovementWander/WanderPriority" to="MovementSampler" method="enable"]
+[connection signal="timeout" from="MovementWander/TiredTimer" to="MovementWander" method="clear_direction"]
+[connection signal="changed_target" from="MovementRunFromMouse" to="MovementRunFromMouse/RunFromMousePriority" method="priority_conditional"]
+[connection signal="move" from="MovementRunFromMouse" to="." method="_on_move"]
+[connection signal="move_enabled" from="MovementRunFromMouse" to="MovementWander" method="clear_direction"]
+[connection signal="priority_changed_no_args" from="MovementRunFromMouse/RunFromMousePriority" to="MovementSampler" method="enable"]
+[connection signal="cursor_entered" from="MovementRunFromMouse/CursorSense" to="MovementRunFromMouse" method="set_target"]
+[connection signal="cursor_exited" from="MovementRunFromMouse/CursorSense" to="MovementRunFromMouse" method="clear_target" unbinds=1]
+[connection signal="changed_target" from="MovementRunFromHunter" to="MovementRunFromHunter/RunFromHunterPriority" method="priority_conditional"]
+[connection signal="move" from="MovementRunFromHunter" to="." method="_on_move"]
+[connection signal="move_disabled" from="MovementRunFromHunter" to="MovementWander" method="clear_direction"]
+[connection signal="priority_changed_no_args" from="MovementRunFromHunter/RunFromHunterPriority" to="MovementSampler" method="enable"]
+[connection signal="tracked" from="MovementRunFromHunter/HunterSense" to="MovementRunFromHunter/HunterSense/TargetPicker" method="set_target_if_null"]
+[connection signal="untracked" from="MovementRunFromHunter/HunterSense" to="MovementRunFromHunter/HunterSense/TargetPicker" method="clear_if_target"]
+[connection signal="target_changed" from="MovementRunFromHunter/HunterSense/TargetPicker" to="MovementRunFromHunter" method="set_target" unbinds=1]
+[connection signal="dragged" from="MovementDrag" to="." method="_on_dragged"]
+[connection signal="dragged" from="MovementDrag" to="MovementDrag/DragPriority" method="priority_alternative" unbinds=1]
+[connection signal="dragged" from="MovementDrag" to="MovementDrag/DragSound" method="play" unbinds=1]
+[connection signal="fallen" from="MovementDrag" to="." method="_on_fallen"]
+[connection signal="fallen" from="MovementDrag" to="MovementDrag/DragPriority" method="priority_default"]
+[connection signal="fallen" from="MovementDrag" to="MovementDrag/FallSound" method="play"]
+[connection signal="move" from="MovementDrag" to="." method="_on_move"]
+[connection signal="move_enabled" from="MovementDrag" to="MovementWander" method="clear_direction"]
+[connection signal="priority_changed_no_args" from="MovementDrag/DragPriority" to="MovementSampler" method="enable"]
+[connection signal="dragged" from="MovementDrag/Draggable" to="MovementDrag" method="drag"]
+[connection signal="dropped" from="MovementDrag/Draggable" to="MovementDrag" method="drop"]
diff --git a/entities/sheep_snowy.gd b/entities/sheep_snowy.gd
deleted file mode 100644
index cd0a871..0000000
--- a/entities/sheep_snowy.gd
+++ /dev/null
@@ -1,119 +0,0 @@
-extends RigidBody2D
-
-var initial_self_position: Vector2 = Vector2.ZERO
-var initial_mouse_position: Vector2 = Vector2.ZERO
-
-@onready var rand_walk_timer: Timer = Timer.new()
-var rng = RandomNumberGenerator.new()
-enum State {STATE_IDLE, STATE_WALK, STATE_PICKED, STATE_RUN, STATE_THROWN}
-var state: State = State.STATE_IDLE
-var walk_dir: Vector2 = Vector2.ZERO
-var last_dir: int = 1
-var last_mouse_pos: Vector2 = Vector2.ZERO
-
-
-@export var min_run_dist = 200
-@export var max_run_dist = 250
-
-@export var walk_speed = 150
-@export var run_speed = 500
-
-@export var drag_damp = 40
-@export var normal_damp = 4
-@export var thrown_damp = 2
-
-
-# Called when the node enters the scene tree for the first time.
-func _ready():
- add_child(rand_walk_timer)
- rand_walk_timer.one_shot = true;
- rand_walk_timer.connect("timeout", _on_timer_timeout)
- init_timer()
-
-func init_timer():
- if state == State.STATE_IDLE:
- var rand_time = max(0, rng.randfn(4, 1.5))
- rand_walk_timer.start(rand_time)
- elif state == State.STATE_WALK:
- rand_walk_timer.start(5)
-
-
-# Called every frame. 'delta' is the elapsed time since the previous frame.
-func _process(delta):
- # Update state
- var curr_mpos = get_viewport().get_mouse_position()
- last_mouse_pos = curr_mpos
-
- if state == State.STATE_PICKED and not Input.is_mouse_button_pressed(MOUSE_BUTTON_LEFT):
- pick_down()
-
- var mouse_dis = position.distance_to(curr_mpos)
- if (state == State.STATE_IDLE or state == State.STATE_WALK) and mouse_dis < min_run_dist:
- # Run away from mouse
- state = State.STATE_RUN
- rand_walk_timer.stop()
- elif state == State.STATE_RUN and mouse_dis > max_run_dist:
- state = State.STATE_IDLE
- init_timer()
-
-func _physics_process(delta):
- gravity_scale = 0
- if state == State.STATE_THROWN and linear_velocity.length() < 300:
- linear_velocity = Vector2.ZERO
- state = State.STATE_WALK
- init_timer()
-
- var force = Vector2.ZERO
-
- if state == State.STATE_WALK:
- force = walk_speed * walk_dir
- elif state == State.STATE_RUN:
- var run_dir = -position.direction_to(last_mouse_pos)
- force = run_speed * run_dir
- elif state == State.STATE_PICKED:
- var dest_position = initial_self_position + (last_mouse_pos - initial_mouse_position)
- apply_central_force(50 * (dest_position - position) * dest_position.distance_to(position) * delta)
- else:
- pass
-
- if force.length_squared() > 0.001:
- apply_central_force(force)
- last_dir = sign(force.dot(Vector2.LEFT))
-
- scale.x = last_dir
-
- if state == State.STATE_PICKED:
- linear_damp = drag_damp
- elif state == State.STATE_THROWN:
- linear_damp = thrown_damp
- else:
- linear_damp = normal_damp
-
-
-func _on_input_event(viewport, event, shape_idx):
- if event is InputEventMouseButton:
- var was_picked_up = state == State.STATE_PICKED
- var is_picked_up = event.pressed
- initial_mouse_position = event.position
- initial_self_position = position
-
- if not was_picked_up and is_picked_up:
- state = State.STATE_PICKED
- rand_walk_timer.stop()
- elif was_picked_up and not is_picked_up:
- pick_down()
-
-func pick_down():
- state = State.STATE_THROWN
- init_timer()
-
-
-func _on_timer_timeout():
- if state == State.STATE_IDLE:
- state = State.STATE_WALK
- walk_dir = Vector2.from_angle(rng.randf_range(0, 2*PI))
- elif state == State.STATE_WALK:
- state = State.STATE_IDLE
- init_timer()
-
-
diff --git a/entities/skull.gd b/entities/skull.gd
new file mode 100644
index 0000000..9fcbdc6
--- /dev/null
+++ b/entities/skull.gd
@@ -0,0 +1,16 @@
+extends CharacterBody2D
+class_name Skull
+
+
+func _on_move(movement: Vector2) -> void:
+ move_and_collide(movement)
+
+func _on_dragged(_cursor: Cursor) -> void:
+ collision_layer = 16
+ collision_mask = 18
+ z_index = 1
+
+func _on_fallen() -> void:
+ collision_layer = 8
+ collision_mask = 14
+ z_index = 0
diff --git a/temp/pickup_skull.png b/entities/skull.png
similarity index 100%
rename from temp/pickup_skull.png
rename to entities/skull.png
diff --git a/temp/pickup_skull.png.import b/entities/skull.png.import
similarity index 71%
rename from temp/pickup_skull.png.import
rename to entities/skull.png.import
index b8c9c3f..66a5843 100644
--- a/temp/pickup_skull.png.import
+++ b/entities/skull.png.import
@@ -3,15 +3,15 @@
importer="texture"
type="CompressedTexture2D"
uid="uid://dwvvwjdexdywh"
-path="res://.godot/imported/pickup_skull.png-c05653658414d7be9a8a5454887e620a.ctex"
+path="res://.godot/imported/skull.png-eb9ec0d464004e0ca27a71e2a33a9dd3.ctex"
metadata={
"vram_texture": false
}
[deps]
-source_file="res://temp/pickup_skull.png"
-dest_files=["res://.godot/imported/pickup_skull.png-c05653658414d7be9a8a5454887e620a.ctex"]
+source_file="res://entities/skull.png"
+dest_files=["res://.godot/imported/skull.png-eb9ec0d464004e0ca27a71e2a33a9dd3.ctex"]
[params]
diff --git a/entities/skull.tscn b/entities/skull.tscn
new file mode 100644
index 0000000..e7d68a9
--- /dev/null
+++ b/entities/skull.tscn
@@ -0,0 +1,49 @@
+[gd_scene load_steps=9 format=3 uid="uid://b3gydtrenbw3n"]
+
+[ext_resource type="Script" path="res://entities/skull.gd" id="1_7g8bu"]
+[ext_resource type="Texture2D" uid="uid://dwvvwjdexdywh" path="res://entities/skull.png" id="1_v6qk3"]
+[ext_resource type="PackedScene" uid="uid://dijcjahkddudv" path="res://behaviours/draggable.tscn" id="2_h0icd"]
+[ext_resource type="PackedScene" uid="uid://rx24bppccih7" path="res://behaviours/move_physics.tscn" id="3_83m1a"]
+[ext_resource type="AudioStream" uid="uid://dq3xf4i2wpt50" path="res://entities/skull_drag.wav" id="5_duqrf"]
+[ext_resource type="AudioStream" uid="uid://cwsg776c11xfc" path="res://entities/fall.ogg" id="6_7yx26"]
+
+[sub_resource type="CircleShape2D" id="CircleShape2D_ypibs"]
+radius = 12.0
+
+[sub_resource type="CircleShape2D" id="CircleShape2D_1c7gd"]
+radius = 12.0
+
+[node name="Skull" type="CharacterBody2D"]
+collision_layer = 8
+collision_mask = 14
+motion_mode = 1
+script = ExtResource("1_7g8bu")
+
+[node name="Sprite" type="Sprite2D" parent="."]
+scale = Vector2(2, 2)
+texture = ExtResource("1_v6qk3")
+
+[node name="Shape" type="CollisionShape2D" parent="."]
+shape = SubResource("CircleShape2D_ypibs")
+
+[node name="MovementDrag" parent="." instance=ExtResource("3_83m1a")]
+
+[node name="Draggable" parent="MovementDrag" instance=ExtResource("2_h0icd")]
+
+[node name="Shape" type="CollisionShape2D" parent="MovementDrag/Draggable"]
+shape = SubResource("CircleShape2D_1c7gd")
+debug_color = Color(1, 1, 1, 0)
+
+[node name="DragSound" type="AudioStreamPlayer2D" parent="MovementDrag"]
+stream = ExtResource("5_duqrf")
+
+[node name="FallSound" type="AudioStreamPlayer2D" parent="MovementDrag"]
+stream = ExtResource("6_7yx26")
+
+[connection signal="dragged" from="MovementDrag" to="." method="_on_dragged"]
+[connection signal="dragged" from="MovementDrag" to="MovementDrag/DragSound" method="play" unbinds=1]
+[connection signal="fallen" from="MovementDrag" to="." method="_on_fallen"]
+[connection signal="fallen" from="MovementDrag" to="MovementDrag/FallSound" method="play"]
+[connection signal="move" from="MovementDrag" to="." method="_on_move"]
+[connection signal="dragged" from="MovementDrag/Draggable" to="MovementDrag" method="drag"]
+[connection signal="dropped" from="MovementDrag/Draggable" to="MovementDrag" method="drop"]
diff --git a/temp/bones.wav b/entities/skull_drag.wav
similarity index 100%
rename from temp/bones.wav
rename to entities/skull_drag.wav
diff --git a/temp/bones.wav.import b/entities/skull_drag.wav.import
similarity index 55%
rename from temp/bones.wav.import
rename to entities/skull_drag.wav.import
index 8ba7e5d..cdd80ac 100644
--- a/temp/bones.wav.import
+++ b/entities/skull_drag.wav.import
@@ -3,12 +3,12 @@
importer="wav"
type="AudioStreamWAV"
uid="uid://dq3xf4i2wpt50"
-path="res://.godot/imported/bones.wav-53a2d1735511ef1f1bf2921348b332aa.sample"
+path="res://.godot/imported/skull_drag.wav-b4fa618d3799af68752c0db13a8d9e22.sample"
[deps]
-source_file="res://temp/bones.wav"
-dest_files=["res://.godot/imported/bones.wav-53a2d1735511ef1f1bf2921348b332aa.sample"]
+source_file="res://entities/skull_drag.wav"
+dest_files=["res://.godot/imported/skull_drag.wav-b4fa618d3799af68752c0db13a8d9e22.sample"]
[params]
diff --git a/entities/top_hat.gd b/entities/top_hat.gd
new file mode 100644
index 0000000..1c66e29
--- /dev/null
+++ b/entities/top_hat.gd
@@ -0,0 +1,16 @@
+extends CharacterBody2D
+class_name TopHat
+
+
+func _on_move(movement: Vector2) -> void:
+ move_and_collide(movement)
+
+func _on_dragged(_cursor: Cursor) -> void:
+ collision_layer = 16
+ collision_mask = 18
+ z_index = 1
+
+func _on_fallen() -> void:
+ collision_layer = 8
+ collision_mask = 14
+ z_index = 0
diff --git a/temp/pickup_tophat.png b/entities/top_hat.png
similarity index 100%
rename from temp/pickup_tophat.png
rename to entities/top_hat.png
diff --git a/temp/pickup_tophat.png.import b/entities/top_hat.png.import
similarity index 71%
rename from temp/pickup_tophat.png.import
rename to entities/top_hat.png.import
index fbf98b0..c07aa55 100644
--- a/temp/pickup_tophat.png.import
+++ b/entities/top_hat.png.import
@@ -3,15 +3,15 @@
importer="texture"
type="CompressedTexture2D"
uid="uid://deqvgvf66grr4"
-path="res://.godot/imported/pickup_tophat.png-cd26d2618474ae83136bd7a01c578302.ctex"
+path="res://.godot/imported/top_hat.png-f606d6a390df7c1cf302806971027b77.ctex"
metadata={
"vram_texture": false
}
[deps]
-source_file="res://temp/pickup_tophat.png"
-dest_files=["res://.godot/imported/pickup_tophat.png-cd26d2618474ae83136bd7a01c578302.ctex"]
+source_file="res://entities/top_hat.png"
+dest_files=["res://.godot/imported/top_hat.png-f606d6a390df7c1cf302806971027b77.ctex"]
[params]
diff --git a/entities/top_hat.tscn b/entities/top_hat.tscn
new file mode 100644
index 0000000..05bd86f
--- /dev/null
+++ b/entities/top_hat.tscn
@@ -0,0 +1,48 @@
+[gd_scene load_steps=8 format=3 uid="uid://8ejgwtkpaa44"]
+
+[ext_resource type="Script" path="res://entities/top_hat.gd" id="1_0eh11"]
+[ext_resource type="Texture2D" uid="uid://deqvgvf66grr4" path="res://entities/top_hat.png" id="1_gbqic"]
+[ext_resource type="PackedScene" uid="uid://rx24bppccih7" path="res://behaviours/move_physics.tscn" id="3_gy414"]
+[ext_resource type="PackedScene" uid="uid://dijcjahkddudv" path="res://behaviours/draggable.tscn" id="4_fcvjo"]
+[ext_resource type="AudioStream" uid="uid://cwsg776c11xfc" path="res://entities/fall.ogg" id="6_6tpnh"]
+
+[sub_resource type="CircleShape2D" id="CircleShape2D_o7chm"]
+radius = 12.0
+
+[sub_resource type="CircleShape2D" id="CircleShape2D_juisb"]
+radius = 12.0
+
+[node name="TopHat" type="CharacterBody2D"]
+collision_layer = 8
+collision_mask = 14
+motion_mode = 1
+script = ExtResource("1_0eh11")
+
+[node name="Sprite" type="Sprite2D" parent="."]
+scale = Vector2(2, 2)
+texture = ExtResource("1_gbqic")
+
+[node name="Shape" type="CollisionShape2D" parent="."]
+shape = SubResource("CircleShape2D_o7chm")
+
+[node name="MovementDrag" parent="." instance=ExtResource("3_gy414")]
+
+[node name="Draggable" parent="MovementDrag" instance=ExtResource("4_fcvjo")]
+collision_layer = 32
+
+[node name="Shape" type="CollisionShape2D" parent="MovementDrag/Draggable"]
+shape = SubResource("CircleShape2D_juisb")
+debug_color = Color(1, 1, 1, 0)
+
+[node name="DragSound" type="AudioStreamPlayer2D" parent="MovementDrag"]
+
+[node name="FallSound" type="AudioStreamPlayer2D" parent="MovementDrag"]
+stream = ExtResource("6_6tpnh")
+
+[connection signal="dragged" from="MovementDrag" to="." method="_on_dragged"]
+[connection signal="dragged" from="MovementDrag" to="MovementDrag/DragSound" method="play" unbinds=1]
+[connection signal="fallen" from="MovementDrag" to="." method="_on_fallen"]
+[connection signal="fallen" from="MovementDrag" to="MovementDrag/FallSound" method="play"]
+[connection signal="move" from="MovementDrag" to="." method="_on_move"]
+[connection signal="dragged" from="MovementDrag/Draggable" to="MovementDrag" method="drag"]
+[connection signal="dropped" from="MovementDrag/Draggable" to="MovementDrag" method="drop"]
diff --git a/random.gd b/random.gd
index 11f0915..baed659 100644
--- a/random.gd
+++ b/random.gd
@@ -10,3 +10,15 @@ static var rng: RandomNumberGenerator = null:
return rng
set(value):
rng = value
+
+
+static func sample(array: Array[Variant], imin = null, imax = null) -> Variant:
+ if len(array) == 0:
+ Log.w(null, "Sampling from an empty array.")
+ return null
+ if imin == null:
+ imin = 0
+ if imax == null:
+ imax = len(array) - 1
+ var idx = rng.randi_range(imin, imax)
+ return array[idx]
diff --git a/scenes/game/cursor_magnet.gd b/scenes/game/cursor.gd
similarity index 56%
rename from scenes/game/cursor_magnet.gd
rename to scenes/game/cursor.gd
index 1f71ec9..d211b0f 100644
--- a/scenes/game/cursor_magnet.gd
+++ b/scenes/game/cursor.gd
@@ -1,31 +1,42 @@
extends Area2D
-class_name CursorMagnet
+class_name Cursor
+
+## A [CharacterBody2D] syncing its position with the mouse on each physics timestep.
signal dragged(node: Draggable)
signal dropped(node: Draggable)
+@onready var game := MainGame.get_via_group(self)
+
+var dragging: Draggable = null
+
+
+static func get_via_group(node: Node) -> MainGame:
+ var result = node.get_tree().get_nodes_in_group("cursor")
+ if result.is_empty():
+ return null
+ return result[0]
+
+
func find_closest_target() -> Draggable:
var bodies = get_overlapping_bodies()
var min_distance: float = INF
var to_drag: Node = null
for body in bodies:
- for target in body.find_children("Draggable", "Draggable", false, false):
+ for target in body.find_children("*", "Draggable", true, false):
var distance = position.distance_to(target.position)
if distance < min_distance:
min_distance = distance
to_drag = target
return to_drag
-
-var dragging: Draggable = null
-
func drag():
var target = find_closest_target()
- if target:
+ if target and not dragging:
dragging = target
- target.drag()
+ target.drag(self)
dragged.emit(target)
func drop():
@@ -35,6 +46,9 @@ func drop():
target.drop()
dropped.emit(target)
+func log_dragging() -> void:
+ Log.p(self, "Dragging: %s" % dragging)
+
func _input(event: InputEvent) -> void:
if event is InputEventMouseButton:
@@ -44,11 +58,5 @@ func _input(event: InputEvent) -> void:
else:
drop()
-func _on_dragged(node: Draggable) -> void:
- Log.p(self, "Dragged: %s" % node)
-
-func _on_dropped(node: Draggable) -> void:
- Log.p(self, "Dropped: %s" % node)
-
-func _on_move(movement: Vector2) -> void:
- position += movement
+func _physics_process(_delta: float) -> void:
+ position += (game.camera.get_global_mouse_position() - global_position)
diff --git a/scenes/game/cursor.tscn b/scenes/game/cursor.tscn
new file mode 100644
index 0000000..a85fb27
--- /dev/null
+++ b/scenes/game/cursor.tscn
@@ -0,0 +1,16 @@
+[gd_scene load_steps=3 format=3 uid="uid://col1q3elvkfwk"]
+
+[ext_resource type="Script" path="res://scenes/game/cursor.gd" id="1_1og6v"]
+
+[sub_resource type="CircleShape2D" id="CircleShape2D_j2mj5"]
+radius = 4.0
+
+[node name="Cursor" type="Area2D" groups=["cursor"]]
+z_index = 100
+collision_layer = 64
+collision_mask = 40
+script = ExtResource("1_1og6v")
+
+[node name="Shape" type="CollisionShape2D" parent="."]
+shape = SubResource("CircleShape2D_j2mj5")
+debug_color = Color(1, 1, 1, 1)
diff --git a/scenes/game/cursor_magnet.tscn b/scenes/game/cursor_magnet.tscn
deleted file mode 100644
index 05866a1..0000000
--- a/scenes/game/cursor_magnet.tscn
+++ /dev/null
@@ -1,25 +0,0 @@
-[gd_scene load_steps=4 format=3 uid="uid://7j1b55t8tafg"]
-
-[ext_resource type="Script" path="res://scenes/game/cursor_magnet.gd" id="1_xk040"]
-[ext_resource type="PackedScene" uid="uid://bvrxvrjlo5130" path="res://behaviours/move_towards_mouse.tscn" id="2_ljil3"]
-
-[sub_resource type="CircleShape2D" id="CircleShape2D_6mkjn"]
-radius = 16.0
-
-[node name="CursorMagnet" type="Area2D"]
-collision_layer = 64
-collision_mask = 8
-script = ExtResource("1_xk040")
-
-[node name="Shape" type="CollisionShape2D" parent="."]
-scale = Vector2(0.5, 0.5)
-shape = SubResource("CircleShape2D_6mkjn")
-debug_color = Color(1, 1, 1, 0.67451)
-
-[node name="MoveTowardsMouse" parent="." instance=ExtResource("2_ljil3")]
-scale = Vector2(10000, 10000)
-speed = 100000.0
-
-[connection signal="dragged" from="." to="." method="_on_dragged"]
-[connection signal="dropped" from="." to="." method="_on_dropped"]
-[connection signal="move" from="MoveTowardsMouse" to="." method="_on_move"]
diff --git a/scenes/game/inventory.gd b/scenes/game/inventory.gd
new file mode 100644
index 0000000..eaa56e9
--- /dev/null
+++ b/scenes/game/inventory.gd
@@ -0,0 +1,20 @@
+extends Node
+class_name Inventory
+
+
+signal new_counter_created(kind: StringName, counter: Counter)
+
+
+@export var counter_scene: PackedScene
+
+
+func get_counter(kind: StringName) -> Counter:
+ var path: NodePath = NodePath(kind)
+ var counter: Counter = get_node_or_null(path)
+ if counter != null:
+ return counter
+ counter = counter_scene.instantiate()
+ counter.name = kind
+ add_child(counter)
+ new_counter_created.emit(kind, counter)
+ return counter
diff --git a/scenes/game/inventory.tscn b/scenes/game/inventory.tscn
new file mode 100644
index 0000000..1864338
--- /dev/null
+++ b/scenes/game/inventory.tscn
@@ -0,0 +1,9 @@
+[gd_scene load_steps=3 format=3 uid="uid://cu6mvnfa01nb6"]
+
+[ext_resource type="Script" path="res://scenes/game/inventory.gd" id="1_yji81"]
+[ext_resource type="PackedScene" uid="uid://brvbtvt4em32" path="res://behaviours/counter.tscn" id="2_vhog3"]
+
+[node name="Inventory" type="Node"]
+script = ExtResource("1_yji81")
+
+[node name="Gold" parent="." instance=ExtResource("2_vhog3")]
diff --git a/scenes/game/main_game.gd b/scenes/game/main_game.gd
index 76ba8a4..c6612e2 100644
--- a/scenes/game/main_game.gd
+++ b/scenes/game/main_game.gd
@@ -2,16 +2,13 @@ extends Node2D
class_name MainGame
-## Get the first possible [MainGame] instance by climbing the scene tree one ancestor at a time.
-static func get_ancestor(start: Node) -> MainGame:
- var current = start
- while current is Node:
- if current is MainGame:
- return current
- current = current.get_parent()
- Log.w(start, "MainGame ancestor not found.")
- return null
-
-
-@onready var gold_counter: Counter = $"GoldCounter"
@onready var camera: GameCamera = $"GameCamera"
+@onready var default_spawn_parent: Node2D = %"DefaultSpawnParent"
+@onready var inventory: Inventory = %"Inventory"
+
+
+static func get_via_group(node: Node) -> MainGame:
+ var result = node.get_tree().get_nodes_in_group("game")
+ if result.is_empty():
+ return null
+ return result[0]
diff --git a/scenes/game/main_game.tscn b/scenes/game/main_game.tscn
index 2878937..18bbdd9 100644
--- a/scenes/game/main_game.tscn
+++ b/scenes/game/main_game.tscn
@@ -1,14 +1,15 @@
[gd_scene load_steps=14 format=3 uid="uid://cxj5aud02f40j"]
[ext_resource type="Script" path="res://scenes/game/main_game.gd" id="1_wiglu"]
-[ext_resource type="PackedScene" path="res://behaviours/spawner.tscn" id="2_bx37o"]
[ext_resource type="PackedScene" uid="uid://dm068vaseh45n" path="res://scenes/game/game_camera.tscn" id="2_db5xs"]
+[ext_resource type="PackedScene" uid="uid://cu6mvnfa01nb6" path="res://scenes/game/inventory.tscn" id="2_jhbbf"]
[ext_resource type="Texture2D" uid="uid://d13j4br4hxek6" path="res://scenes/game/tileset_grass.png" id="2_o7bg5"]
-[ext_resource type="PackedScene" uid="uid://brvbtvt4em32" path="res://behaviours/counter.tscn" id="3_p6jw3"]
-[ext_resource type="PackedScene" uid="uid://eqb3vfbvjefp" path="res://entities/cloud.tscn" id="3_whlmm"]
-[ext_resource type="PackedScene" uid="uid://7j1b55t8tafg" path="res://scenes/game/cursor_magnet.tscn" id="3_xbolm"]
-[ext_resource type="Texture2D" uid="uid://dyvkvmw7wxwe5" path="res://icon.svg" id="9_8kxq4"]
-[ext_resource type="PackedScene" uid="uid://4d3ksr3171x4" path="res://entities/imp.tscn" id="10_26rf6"]
+[ext_resource type="PackedScene" uid="uid://col1q3elvkfwk" path="res://scenes/game/cursor.tscn" id="5_g504x"]
+[ext_resource type="PackedScene" uid="uid://b3gydtrenbw3n" path="res://entities/skull.tscn" id="6_5k7gy"]
+[ext_resource type="PackedScene" uid="uid://b04xhv32ypi42" path="res://entities/monocle.tscn" id="7_lahut"]
+[ext_resource type="PackedScene" uid="uid://8ejgwtkpaa44" path="res://entities/top_hat.tscn" id="8_atoon"]
+[ext_resource type="PackedScene" uid="uid://bc2bm8lbol18w" path="res://entities/sheep.tscn" id="9_qrqqu"]
+[ext_resource type="PackedScene" uid="uid://4d3ksr3171x4" path="res://entities/imp.tscn" id="10_yw228"]
[sub_resource type="TileSetAtlasSource" id="TileSetAtlasSource_058kb"]
texture = ExtResource("2_o7bg5")
@@ -813,54 +814,93 @@ terrain_set_0/terrain_1/name = "Dirt"
terrain_set_0/terrain_1/color = Color(0.619608, 0.407843, 0.172549, 1)
sources/0 = SubResource("TileSetAtlasSource_058kb")
-[sub_resource type="RectangleShape2D" id="RectangleShape2D_p1lg5"]
-size = Vector2(1280, 720)
+[sub_resource type="WorldBoundaryShape2D" id="WorldBoundaryShape2D_htttx"]
-[sub_resource type="CircleShape2D" id="CircleShape2D_3du4x"]
-radius = 29.14
-
-[node name="MainGame" type="Node2D"]
+[node name="MainGame" type="Node2D" groups=["game"]]
script = ExtResource("1_wiglu")
+[node name="Inventory" parent="." instance=ExtResource("2_jhbbf")]
+unique_name_in_owner = true
+
[node name="TileMap" type="TileMap" parent="."]
scale = Vector2(2, 2)
tile_set = SubResource("TileSet_g2dkm")
format = 2
-layer_0/tile_data = PackedInt32Array(720915, 196608, 9, 655379, 0, 2, 589843, 0, 4, 524307, 196608, 8, 458771, 196608, 0, 393235, 327680, 1, 327699, 327680, 2, 262163, 65536, 5, 196627, 327680, 0, 131091, 196608, 4, 65555, 0, 6, 19, 0, 6, -65517, 0, 6, -131053, 196608, 1, -196589, 327680, 2, -262125, 327680, 4, -327661, 327680, 1, -393197, 0, 3, -458733, 65536, 0, -524269, 196608, 0, -589805, 327680, 0, -655341, 0, 3, -720877, 327680, 5, -786413, 131072, 8, 720914, 327680, 1, 655378, 65536, 5, 589842, 327680, 0, 524306, 0, 5, 458770, 327680, 2, 393234, 327680, 1, 327698, 131072, 9, 262162, 327680, 0, 196626, 0, 4, 131090, 262144, 6, 65554, 196608, 2, 18, 131072, 3, -65518, 196608, 3, -131054, 196608, 1, -196590, 196608, 9, -262126, 327680, 4, -327662, 0, 4, -393198, 131072, 5, -458734, 262144, 5, -524270, 131072, 9, -589806, 0, 1, -655342, 65536, 5, -720878, 327680, 4, -786414, 262144, 0, 720913, 0, 5, 655377, 131072, 9, 589841, 196608, 9, 524305, 327680, 5, 458769, 0, 4, 393233, 0, 4, 327697, 327680, 5, 262161, 327680, 0, 196625, 262144, 4, 131089, 0, 6, 65553, 131072, 3, 17, 196608, 3, -65519, 196608, 2, -131055, 131072, 11, -196591, 327680, 1, -262127, 196608, 9, -327663, 0, 5, -393199, 262144, 0, -458735, 131072, 0, -524271, 0, 4, -589807, 0, 1, -655343, 327680, 5, -720879, 0, 3, -786415, 131072, 5, 720912, 131072, 9, 655376, 0, 2, 589840, 327680, 3, 524304, 131072, 8, 458768, 196608, 9, 393232, 196608, 5, 327696, 327680, 4, 262160, 262144, 5, 196624, 262144, 6, 131088, 196608, 3, 65552, 196608, 2, 16, 196608, 3, -65520, 131072, 2, -131056, 131072, 11, -196592, 327680, 0, -262128, 196608, 9, -327664, 262144, 0, -393200, 0, 1, -458736, 0, 5, -524272, 262144, 5, -589808, 196608, 8, -655344, 0, 2, -720880, 327680, 2, -786416, 131072, 0, 720911, 196608, 0, 655375, 327680, 2, 589839, 196608, 0, 524303, 0, 0, 458767, 0, 2, 393231, 196608, 5, 327695, 0, 5, 262159, 262144, 4, 196623, 0, 6, 131087, 131072, 2, 65551, 196608, 2, 15, 196608, 3, -65521, 131072, 2, -131057, 131072, 11, -196593, 0, 2, -262129, 262144, 0, -327665, 262144, 5, -393201, 327680, 0, -458737, 65536, 5, -524273, 196608, 5, -589809, 0, 4, -655345, 327680, 2, -720881, 0, 1, -786417, 0, 5, 720910, 131072, 0, 655374, 327680, 3, 589838, 327680, 4, 524302, 196608, 0, 458766, 327680, 0, 393230, 327680, 3, 327694, 262144, 4, 262158, 0, 6, 196622, 131072, 3, 131086, 131072, 3, 65550, 196608, 2, 14, 196608, 3, -65522, 131072, 2, -131058, 262144, 11, -196594, 65536, 0, -262130, 196608, 5, -327666, 0, 3, -393202, 327680, 3, -458738, 327680, 4, -524274, 131072, 0, -589810, 327680, 3, -655346, 131072, 0, -720882, 65536, 5, -786418, 0, 0, 720909, 131072, 9, 655373, 0, 1, 589837, 262144, 0, 524301, 0, 2, 458765, 0, 0, 393229, 196608, 0, 327693, 65536, 6, 262157, 196608, 2, 196621, 196608, 2, 131085, 131072, 3, 65549, 131072, 2, 13, 131072, 3, -65523, 196608, 2, -131059, 131072, 11, -196595, 262144, 0, -262131, 327680, 1, -327667, 196608, 9, -393203, 65536, 0, -458739, 65536, 0, -524275, 196608, 0, -589811, 0, 2, -655347, 327680, 1, -720883, 0, 4, -786419, 327680, 2, 720908, 262144, 5, 655372, 327680, 4, 589836, 196608, 8, 524300, 0, 3, 458764, 262144, 5, 393228, 262144, 4, 327692, 0, 6, 262156, 131072, 3, 196620, 131072, 2, 131084, 196608, 2, 65548, 131072, 3, 12, 196608, 3, -65524, 327680, 11, -131060, 65536, 1, -196596, 262144, 5, -262132, 131072, 9, -327668, 327680, 1, -393204, 327680, 0, -458740, 0, 3, -524276, 0, 3, -589812, 196608, 9, -655348, 327680, 2, -720884, 131072, 9, -786420, 131072, 0, 720907, 327680, 0, 655371, 65536, 0, 589835, 327680, 2, 524299, 262144, 5, 458763, 65536, 0, 393227, 196608, 6, 327691, 196608, 2, 262155, 131072, 3, 196619, 131072, 2, 131083, 131072, 2, 65547, 196608, 3, 11, 196608, 2, -65525, 262144, 11, -131061, 65536, 5, -196597, 196608, 9, -262133, 131072, 5, -327669, 327680, 5, -393205, 262144, 0, -458741, 0, 0, -524277, 0, 1, -589813, 0, 4, -655349, 327680, 4, -720885, 196608, 0, -786421, 0, 2, 720906, 327680, 4, 655370, 0, 4, 589834, 327680, 2, 524298, 327680, 4, 458762, 131072, 8, 393226, 131072, 4, 327690, 131072, 3, 262154, 196608, 2, 196618, 196608, 3, 131082, 131072, 2, 65546, 131072, 3, 10, 327680, 11, -65526, 65536, 1, -131062, 196608, 0, -196598, 196608, 0, -262134, 196608, 0, -327670, 131072, 8, -393206, 327680, 4, -458742, 327680, 4, -524278, 0, 1, -589814, 0, 0, -655350, 0, 3, -720886, 0, 3, -786422, 327680, 5, 720905, 327680, 0, 655369, 0, 0, 589833, 196608, 0, 524297, 196608, 0, 458761, 0, 1, 393225, 196608, 4, 327689, 196608, 3, 262153, 131072, 3, 196617, 196608, 2, 131081, 196608, 3, 65545, 327680, 11, 9, 65536, 1, -65527, 131072, 9, -131063, 0, 0, -196599, 327680, 0, -262135, 0, 3, -327671, 327680, 1, -393207, 65536, 5, -458743, 196608, 8, -524279, 327680, 3, -589815, 0, 1, -655351, 262144, 0, -720887, 262144, 0, -786423, 196608, 0, 720904, 0, 1, 655368, 262144, 5, 589832, 196608, 5, 524296, 0, 5, 458760, 262144, 4, 393224, 0, 6, 327688, 131072, 3, 262152, 196608, 3, 196616, 196608, 2, 131080, 131072, 2, 65544, 0, 11, 8, 327680, 3, -65528, 262144, 5, -131064, 65536, 5, -196600, 131072, 8, -262136, 327680, 5, -327672, 327680, 1, -393208, 0, 4, -458744, 131072, 0, -524280, 327680, 4, -589816, 131072, 0, -655352, 196608, 5, -720888, 327680, 3, -786424, 196608, 5, 720903, 327680, 5, 655367, 0, 5, 589831, 0, 5, 524295, 65536, 0, 458759, 196608, 4, 393223, 131072, 2, 327687, 196608, 2, 262151, 131072, 2, 196615, 196608, 3, 131079, 131072, 3, 65543, 131072, 3, 7, 262144, 5, -65529, 327680, 3, -131065, 196608, 5, -196601, 0, 2, -262137, 327680, 0, -327673, 327680, 1, -393209, 262144, 4, -458745, 0, 8, -524281, 262144, 3, -589817, 262144, 1, -655353, 327680, 5, -720889, 131072, 8, -786425, 0, 4, 720902, 327680, 2, 655366, 0, 3, 589830, 65536, 0, 524294, 0, 5, 458758, 131072, 4, 393222, 131072, 2, 327686, 196608, 3, 262150, 196608, 2, 196614, 131072, 2, 131078, 131072, 3, 65542, 131072, 3, 6, 327680, 5, -65530, 327680, 5, -131066, 327680, 0, -196602, 131072, 9, -262138, 262144, 4, -327674, 0, 8, -393210, 0, 6, -458746, 131072, 3, -524282, 327680, 11, -589818, 65536, 1, -655354, 0, 0, -720890, 327680, 2, -786426, 196608, 9, 720901, 65536, 5, 655365, 196608, 5, 589829, 196608, 0, 524293, 0, 4, 458757, 196608, 4, 393221, 131072, 2, 327685, 196608, 2, 262149, 131072, 2, 196613, 131072, 3, 131077, 131072, 2, 65541, 196608, 2, 5, 0, 3, -65531, 196608, 0, -131067, 327680, 4, -196603, 327680, 0, -262139, 131072, 6, -327675, 131072, 3, -393211, 196608, 3, -458747, 131072, 3, -524283, 196608, 11, -589819, 0, 2, -655355, 327680, 0, -720891, 131072, 9, -786427, 262144, 5, 720900, 196608, 0, 655364, 196608, 8, 589828, 0, 2, 524292, 327680, 0, 458756, 65536, 6, 393220, 131072, 3, 327684, 131072, 2, 262148, 196608, 3, 196612, 196608, 3, 131076, 196608, 2, 65540, 131072, 3, 4, 0, 3, -65532, 262144, 0, -131068, 131072, 0, -196604, 327680, 0, -262140, 65536, 6, -327676, 196608, 3, -393212, 131072, 2, -458748, 327680, 11, -524284, 65536, 1, -589820, 196608, 0, -655356, 0, 4, -720892, 65536, 5, -786428, 0, 1, 720899, 65536, 0, 655363, 131072, 5, 589827, 131072, 5, 524291, 0, 1, 458755, 65536, 4, 393219, 327680, 6, 327683, 196608, 2, 262147, 196608, 2, 196611, 131072, 3, 131075, 327680, 11, 65539, 327680, 8, 3, 0, 1, -65533, 131072, 0, -131069, 327680, 2, -196605, 65536, 0, -262141, 65536, 4, -327677, 327680, 10, -393213, 65536, 2, -458749, 65536, 1, -524285, 327680, 2, -589821, 0, 3, -655357, 131072, 9, -720893, 0, 2, -786429, 196608, 9, 720898, 131072, 0, 655362, 262144, 0, 589826, 327680, 5, 524290, 327680, 1, 458754, 262144, 0, 393218, 196608, 4, 327682, 196608, 2, 262146, 131072, 3, 196610, 196608, 2, 131074, 131072, 11, 65538, 327680, 4, 2, 0, 3, -65534, 0, 1, -131070, 0, 0, -196606, 327680, 0, -262142, 0, 5, -327678, 65536, 0, -393214, 65536, 5, -458750, 131072, 9, -524286, 196608, 0, -589822, 196608, 0, -655358, 0, 5, -720894, 196608, 9, -786430, 0, 5, 720897, 0, 4, 655361, 262144, 5, 589825, 327680, 0, 524289, 327680, 5, 458753, 327680, 5, 393217, 131072, 6, 327681, 131072, 2, 262145, 196608, 3, 196609, 131072, 2, 131073, 131072, 11, 65537, 131072, 9, 1, 0, 4, -65535, 196608, 0, -131071, 327680, 3, -196607, 196608, 0, -262143, 0, 4, -327679, 262144, 5, -393215, 196608, 5, -458751, 0, 2, -524287, 196608, 9, -589823, 196608, 0, -655359, 131072, 0, -720895, 0, 3, -786431, 196608, 8, 720896, 262144, 5, 655360, 0, 4, 589824, 0, 2, 524288, 0, 0, 458752, 196608, 9, 393216, 196608, 4, 327680, 196608, 3, 262144, 131072, 3, 196608, 131072, 3, 131072, 0, 11, 65536, 327680, 3, 0, 65536, 0, -65536, 196608, 5, -131072, 196608, 9, -196608, 65536, 0, -262144, 0, 5, -327680, 65536, 0, -393216, 0, 3, -458752, 327680, 0, -524288, 0, 3, -589824, 327680, 2, -655360, 131072, 8, -720896, 327680, 3, -786432, 196608, 8, 786431, 0, 3, 720895, 131072, 0, 655359, 196608, 8, 589823, 196608, 8, 524287, 327680, 0, 458751, 196608, 4, 393215, 131072, 3, 327679, 131072, 3, 262143, 196608, 3, 196607, 131072, 3, 131071, 262144, 0, 65535, 131072, 8, -1, 0, 0, -65537, 327680, 3, -131073, 131072, 9, -196609, 327680, 0, -262145, 131072, 0, -327681, 0, 0, -393217, 131072, 9, -458753, 196608, 8, -524289, 327680, 5, -589825, 0, 1, -655361, 196608, 0, -720897, 196608, 8, 786430, 327680, 3, 720894, 65536, 0, 655358, 262144, 0, 589822, 327680, 2, 524286, 131072, 0, 458750, 131072, 4, 393214, 131072, 2, 327678, 196608, 2, 262142, 131072, 2, 196606, 327680, 11, 131070, 327680, 2, 65534, 196608, 0, -2, 65536, 5, -65538, 196608, 8, -131074, 327680, 3, -196610, 131072, 8, -262146, 327680, 1, -327682, 262144, 5, -393218, 0, 1, -458754, 327680, 4, -524290, 262144, 5, -589826, 327680, 4, -655362, 327680, 1, -720898, 131072, 8, 786429, 0, 5, 720893, 0, 4, 655357, 196608, 5, 589821, 0, 4, 524285, 262144, 0, 458749, 262144, 6, 393213, 131072, 3, 327677, 131072, 2, 262141, 327680, 11, 196605, 65536, 1, 131069, 327680, 3, 65533, 0, 3, -3, 327680, 1, -65539, 327680, 4, -131075, 131072, 5, -196611, 262144, 4, -262147, 0, 10, -327683, 262144, 1, -393219, 196608, 8, -458755, 196608, 9, -524291, 0, 2, -589827, 262144, 0, -655363, 327680, 4, -720899, 327680, 4, 786428, 131072, 9, 720892, 131072, 0, 655356, 0, 5, 589820, 262144, 4, 524284, 0, 8, 458748, 0, 6, 393212, 131072, 3, 327676, 196608, 2, 262140, 196608, 11, 196604, 65536, 0, 131068, 196608, 0, 65532, 65536, 0, -4, 131072, 8, -65540, 196608, 5, -131076, 0, 2, -196612, 65536, 6, -262148, 196608, 2, -327684, 262144, 11, -393220, 0, 0, -458756, 131072, 9, -524292, 65536, 5, -589828, 131072, 0, -655364, 0, 2, -720900, 0, 0, 786427, 0, 3, 720891, 327680, 2, 655355, 0, 0, 589819, 65536, 6, 524283, 196608, 3, 458747, 131072, 2, 393211, 131072, 3, 327675, 327680, 11, 262139, 65536, 1, 196603, 131072, 0, 131067, 327680, 5, 65531, 0, 1, -5, 131072, 9, -65541, 196608, 5, -131077, 131072, 8, -196613, 262144, 6, -262149, 196608, 2, -327685, 0, 11, -393221, 262144, 1, -458757, 327680, 2, -524293, 196608, 0, -589829, 131072, 5, -655365, 262144, 0, -720901, 0, 4, 786426, 131072, 9, 720890, 262144, 0, 655354, 0, 0, 589818, 131072, 6, 524282, 196608, 2, 458746, 196608, 3, 393210, 196608, 3, 327674, 131072, 1, 262138, 196608, 5, 196602, 262144, 0, 131066, 196608, 8, 65530, 327680, 3, -6, 327680, 5, -65542, 0, 4, -131078, 196608, 8, -196614, 262144, 6, -262150, 131072, 3, -327686, 131072, 2, -393222, 196608, 1, -458758, 262144, 5, -524294, 0, 4, -589830, 131072, 5, -655366, 0, 5, -720902, 327680, 2, 786425, 0, 4, 720889, 0, 1, 655353, 0, 0, 589817, 131072, 6, 524281, 196608, 2, 458745, 131072, 2, 393209, 196608, 2, 327673, 262144, 11, 262137, 0, 0, 196601, 327680, 5, 131065, 65536, 0, 65529, 131072, 9, -7, 131072, 8, -65543, 131072, 0, -131079, 262144, 4, -196615, 0, 6, -262151, 131072, 3, -327687, 131072, 3, -393223, 0, 11, -458759, 262144, 1, -524295, 327680, 4, -589831, 262144, 5, -655367, 131072, 8, -720903, 0, 5, 786424, 327680, 3, 720888, 196608, 5, 655352, 131072, 9, 589816, 131072, 6, 524280, 196608, 2, 458744, 196608, 2, 393208, 196608, 2, 327672, 196608, 1, 262136, 0, 3, 196600, 0, 2, 131064, 327680, 0, 65528, 0, 5, -8, 0, 1, -65544, 196608, 5, -131080, 196608, 6, -196616, 131072, 3, -262152, 196608, 3, -327688, 196608, 3, -393224, 131072, 3, -458760, 196608, 1, -524296, 0, 3, -589832, 131072, 9, -655368, 0, 4, -720904, 131072, 5, 786423, 0, 0, 720887, 131072, 8, 655351, 0, 9, 589815, 0, 6, 524279, 196608, 2, 458743, 196608, 3, 393207, 131072, 2, 327671, 131072, 1, 262135, 0, 1, 196599, 196608, 8, 131063, 262144, 5, 65527, 262144, 5, -9, 0, 5, -65545, 262144, 4, -131081, 0, 6, -196617, 196608, 3, -262153, 196608, 3, -327689, 131072, 2, -393225, 196608, 2, -458761, 65536, 11, -524297, 131072, 8, -589833, 196608, 0, -655369, 196608, 9, -720905, 196608, 0, 786422, 196608, 9, 720886, 327680, 1, 655350, 327680, 6, 589814, 196608, 3, 524278, 131072, 2, 458742, 131072, 3, 393206, 327680, 11, 327670, 131072, 1, 262134, 131072, 9, 196598, 327680, 4, 131062, 0, 1, 65526, 196608, 9, -10, 65536, 5, -65546, 65536, 4, -131082, 327680, 6, -196618, 196608, 3, -262154, 131072, 3, -327690, 131072, 3, -393226, 327680, 11, -458762, 65536, 1, -524298, 0, 1, -589834, 196608, 9, -655370, 327680, 5, -720906, 327680, 5, 786421, 0, 0, 720885, 327680, 3, 655349, 262144, 6, 589813, 131072, 2, 524277, 196608, 3, 458741, 327680, 11, 393205, 65536, 1, 327669, 196608, 9, 262133, 0, 1, 196597, 327680, 0, 131061, 0, 5, 65525, 131072, 0, -11, 327680, 0, -65547, 131072, 0, -131083, 65536, 4, -196619, 327680, 9, -262155, 327680, 9, -327691, 327680, 7, -393227, 65536, 1, -458763, 327680, 4, -524299, 327680, 5, -589835, 196608, 8, -655371, 0, 3, -720907, 196608, 0, 786420, 131072, 0, 720884, 262144, 4, 655348, 0, 6, 589812, 131072, 2, 524276, 196608, 3, 458740, 131072, 11, 393204, 327680, 5, 327668, 196608, 9, 262132, 196608, 9, 196596, 65536, 5, 131060, 196608, 5, 65524, 131072, 8, -12, 65536, 5, -65548, 65536, 5, -131084, 262144, 5, -196620, 0, 1, -262156, 327680, 5, -327692, 0, 4, -393228, 196608, 0, -458764, 327680, 1, -524300, 65536, 0, -589836, 0, 5, -655372, 262144, 0, -720908, 327680, 4, 786419, 131072, 0, 720883, 262144, 6, 655347, 131072, 3, 589811, 131072, 2, 524275, 196608, 3, 458739, 131072, 1, 393203, 196608, 0, 327667, 0, 5, 262131, 0, 3, 196595, 0, 5, 131059, 196608, 5, 65523, 262144, 0, -13, 131072, 5, -65549, 327680, 2, -131085, 0, 5, -196621, 196608, 9, -262157, 0, 3, -327693, 131072, 8, -393229, 131072, 9, -458765, 65536, 5, -524301, 327680, 0, -589837, 65536, 0, -655373, 0, 2, -720909, 131072, 8, 786418, 327680, 5, 720882, 262144, 6, 655346, 196608, 2, 589810, 131072, 3, 524274, 131072, 2, 458738, 262144, 11, 393202, 196608, 5, 327666, 262144, 0, 262130, 262144, 0, 196594, 327680, 0, 131058, 327680, 1, 65522, 65536, 0, -14, 65536, 5, -65550, 327680, 0, -131086, 0, 0, -196622, 131072, 5, -262158, 327680, 2, -327694, 0, 3, -393230, 0, 0, -458766, 327680, 1, -524302, 327680, 1, -589838, 131072, 5, -655374, 131072, 8, -720910, 65536, 0, 786417, 262144, 4, 720881, 0, 6, 655345, 196608, 2, 589809, 196608, 2, 524273, 196608, 2, 458737, 131072, 1, 393201, 196608, 9, 327665, 65536, 0, 262129, 131072, 8, 196593, 0, 5, 131057, 0, 3, 65521, 196608, 0, -15, 131072, 5, -65551, 327680, 5, -131087, 0, 5, -196623, 131072, 9, -262159, 196608, 5, -327695, 0, 5, -393231, 0, 0, -458767, 0, 2, -524303, 131072, 0, -589839, 196608, 9, -655375, 262144, 5, -720911, 327680, 3, 786416, 196608, 2, 720880, 131072, 2, 655344, 196608, 3, 589808, 196608, 2, 524272, 327680, 11, 458736, 65536, 1, 393200, 0, 5, 327664, 131072, 0, 262128, 196608, 9, 196592, 65536, 0, 131056, 65536, 5, 65520, 327680, 1, -16, 131072, 9, -65552, 327680, 0, -131088, 0, 3, -196624, 327680, 0, -262160, 327680, 3, -327696, 65536, 0, -393232, 196608, 9, -458768, 65536, 0, -524304, 0, 0, -589840, 327680, 2, -655376, 327680, 3, -720912, 0, 5, 786415, 196608, 2, 720879, 131072, 3, 655343, 131072, 2, 589807, 196608, 2, 524271, 65536, 11, 458735, 65536, 5, 393199, 0, 4, 327663, 131072, 5, 262127, 262144, 0, 196591, 196608, 5, 131055, 327680, 4, 65519, 327680, 0, -17, 327680, 0, -65553, 262144, 5, -131089, 0, 4, -196625, 0, 2, -262161, 196608, 9, -327697, 0, 3, -393233, 196608, 5, -458769, 327680, 3, -524305, 327680, 2, -589841, 327680, 1, -655377, 327680, 3, -720913, 0, 2, 786414, 131072, 3, 720878, 131072, 2, 655342, 196608, 3, 589806, 327680, 11, 524270, 65536, 1, 458734, 0, 0, 393198, 0, 5, 327662, 131072, 5, 262126, 327680, 3, 196590, 65536, 0, 131054, 196608, 8, 65518, 0, 5, -18, 65536, 5, -65554, 327680, 0, -131090, 327680, 3, -196626, 0, 0, -262162, 0, 3, -327698, 262144, 0, -393234, 262144, 0, -458770, 65536, 0, -524306, 131072, 0, -589842, 0, 1, -655378, 327680, 2, -720914, 196608, 5, 786413, 196608, 3, 720877, 131072, 3, 655341, 327680, 11, 589805, 65536, 1, 524269, 327680, 4, 458733, 327680, 2, 393197, 0, 3, 327661, 0, 3, 262125, 196608, 9, 196589, 327680, 0, 131053, 65536, 5, 65517, 327680, 5, -19, 65536, 5, -65555, 196608, 8, -131091, 131072, 0, -196627, 131072, 5, -262163, 327680, 5, -327699, 327680, 2, -393235, 262144, 5, -458771, 196608, 8, -524307, 327680, 3, -589843, 327680, 0, -655379, 0, 3, -720915, 131072, 5, 786412, 196608, 2, 720876, 196608, 3, 655340, 262144, 11, 589804, 0, 3, 524268, 327680, 3, 458732, 0, 4, 393196, 131072, 5, 327660, 327680, 3, 262124, 131072, 5, 196588, 0, 4, 131052, 131072, 9, 65516, 0, 3, -20, 327680, 1, -65556, 0, 1, -131092, 327680, 1, -196628, 196608, 5, -262164, 131072, 8, -327700, 196608, 0, -393236, 131072, 5, -458772, 327680, 3, -524308, 327680, 4, -589844, 131072, 5, -655380, 0, 0, -720916, 0, 2)
-
-[node name="CloudSpawner" parent="." instance=ExtResource("2_bx37o")]
-position = Vector2(41.795, -60.05)
-scene = ExtResource("3_whlmm")
-
-[node name="PlayArea" type="Area2D" parent="."]
-
-[node name="Shape" type="CollisionShape2D" parent="PlayArea"]
-shape = SubResource("RectangleShape2D_p1lg5")
-debug_color = Color(1, 1, 1, 0)
+layer_0/tile_data = PackedInt32Array(720915, 196608, 9, 655379, 65536, 10, 589843, 131072, 8, 524307, 0, 5, 458771, 196608, 10, 393235, 131072, 0, 327699, 327680, 5, 262163, 327680, 5, 196627, 65536, 8, 131091, 65536, 0, 65555, 196608, 7, 19, 262144, 9, -65517, 65536, 9, -131053, 262144, 7, -196589, 65536, 5, -262125, 131072, 8, -327661, 196608, 5, -393197, 131072, 7, -458733, 327680, 1, -524269, 327680, 0, -589805, 327680, 4, -655341, 0, 4, -720877, 262144, 5, 720914, 196608, 0, 655378, 131072, 10, 589842, 327680, 5, 524306, 327680, 2, 458770, 196608, 8, 393234, 327680, 3, 327698, 65536, 0, 262162, 327680, 3, 196626, 65536, 7, 131090, 65536, 0, 65554, 262144, 9, 18, 262144, 8, -65518, 0, 0, -131054, 65536, 8, -196590, 65536, 10, -262126, 196608, 9, -327662, 65536, 7, -393198, 262144, 8, -458734, 262144, 10, -524270, 65536, 10, -589806, 65536, 10, -655342, 327680, 4, -720878, 327680, 5, 720913, 196608, 8, 655377, 196608, 9, 589841, 262144, 0, 524305, 131072, 0, 458769, 327680, 0, 393233, 196608, 8, 327697, 262144, 0, 262161, 327680, 4, 196625, 0, 3, 131089, 327680, 2, 65553, 196608, 0, 17, 262144, 8, -65519, 196608, 8, -131055, 196608, 5, -196591, 327680, 1, -262127, 196608, 9, -327663, 131072, 0, -393199, 196608, 10, -458735, 196608, 9, -524271, 327680, 3, -589807, 262144, 7, -655343, 196608, 10, -720879, 65536, 7, 720912, 65536, 0, 655376, 65536, 0, 589840, 65536, 10, 524304, 262144, 7, 458768, 262144, 0, 393232, 262144, 8, 327696, 0, 2, 262160, 327680, 4, 196624, 65536, 5, 131088, 196608, 7, 65552, 327680, 3, 16, 327680, 0, -65520, 262144, 9, -131056, 327680, 4, -196592, 65536, 5, -262128, 262144, 8, -327664, 196608, 9, -393200, 327680, 1, -458736, 196608, 0, -524272, 196608, 5, -589808, 0, 3, -655344, 196608, 9, -720880, 196608, 10, 720911, 65536, 10, 655375, 262144, 9, 589839, 327680, 0, 524303, 196608, 5, 458767, 327680, 3, 393231, 262144, 5, 327695, 327680, 5, 262159, 0, 2, 196623, 196608, 10, 131087, 65536, 7, 65551, 131072, 0, 15, 262144, 5, -65521, 65536, 5, -131057, 0, 1, -196593, 131072, 8, -262129, 131072, 9, -327665, 327680, 2, -393201, 131072, 7, -458737, 131072, 10, -524273, 262144, 7, -589809, 131072, 7, -655345, 0, 5, -720881, 65536, 0, 720910, 196608, 8, 655374, 131072, 10, 589838, 327680, 5, 524302, 65536, 7, 458766, 65536, 0, 393230, 327680, 0, 327694, 196608, 0, 262158, 65536, 8, 196622, 131072, 7, 131086, 65536, 9, 65550, 131072, 10, 14, 0, 3, -65522, 262144, 9, -131058, 327680, 4, -196594, 65536, 8, -262130, 196608, 5, -327666, 131072, 9, -393202, 262144, 9, -458738, 196608, 10, -524274, 196608, 10, -589810, 131072, 0, -655346, 0, 4, -720882, 65536, 7, 720909, 65536, 5, 655373, 131072, 0, 589837, 0, 0, 524301, 327680, 0, 458765, 65536, 0, 393229, 0, 1, 327693, 262144, 5, 262157, 262144, 5, 196621, 65536, 10, 131085, 65536, 9, 65549, 196608, 7, 13, 262144, 0, -65523, 0, 1, -131059, 262144, 7, -196595, 0, 3, -262131, 65536, 8, -327667, 196608, 8, -393203, 196608, 0, -458739, 262144, 7, -524275, 327680, 0, -589811, 327680, 0, -655347, 65536, 8, -720883, 262144, 9, 720908, 327680, 3, 655372, 196608, 0, 589836, 131072, 7, 524300, 327680, 1, 458764, 327680, 5, 393228, 327680, 1, 327692, 196608, 8, 262156, 65536, 5, 196620, 65536, 8, 131084, 196608, 9, 65548, 65536, 7, 12, 327680, 2, -65524, 0, 3, -131060, 262144, 10, -196596, 262144, 8, -262132, 65536, 0, -327668, 65536, 9, -393204, 262144, 7, -458740, 65536, 8, -524276, 65536, 5, -589812, 327680, 0, -655348, 131072, 8, -720884, 196608, 8, 720907, 327680, 2, 655371, 196608, 8, 589835, 65536, 0, 524299, 131072, 0, 458763, 327680, 1, 393227, 65536, 9, 327691, 65536, 9, 262155, 65536, 0, 196619, 262144, 5, 131083, 327680, 1, 65547, 131072, 10, 11, 131072, 7, -65525, 196608, 10, -131061, 0, 1, -196597, 262144, 8, -262133, 196608, 8, -327669, 262144, 7, -393205, 262144, 8, -458741, 196608, 7, -524277, 196608, 7, -589813, 196608, 10, -655349, 0, 3, -720885, 131072, 10, 720906, 196608, 10, 655370, 196608, 0, 589834, 196608, 10, 524298, 327680, 3, 458762, 196608, 10, 393226, 131072, 9, 327690, 131072, 8, 262154, 196608, 9, 196618, 327680, 4, 131082, 196608, 8, 65546, 131072, 5, 10, 65536, 5, -65526, 327680, 3, -131062, 0, 3, -196598, 262144, 5, -262134, 327680, 3, -327670, 0, 2, -393206, 0, 4, -458742, 65536, 5, -524278, 196608, 10, -589814, 327680, 1, -655350, 262144, 0, -720886, 196608, 5, 720905, 131072, 5, 655369, 131072, 0, 589833, 0, 3, 524297, 327680, 0, 458761, 131072, 7, 393225, 327680, 4, 327689, 262144, 9, 262153, 262144, 10, 196617, 65536, 10, 131081, 0, 3, 65545, 65536, 10, 9, 327680, 5, -65527, 131072, 7, -131063, 262144, 9, -196599, 327680, 2, -262135, 327680, 0, -327671, 0, 4, -393207, 262144, 5, -458743, 0, 3, -524279, 65536, 0, -589815, 65536, 0, -655351, 196608, 5, -720887, 131072, 7, 720904, 0, 3, 655368, 0, 2, 589832, 131072, 9, 524296, 327680, 4, 458760, 131072, 9, 393224, 327680, 0, 327688, 327680, 0, 262152, 262144, 8, 196616, 0, 0, 131080, 0, 1, 65544, 65536, 0, 8, 0, 1, -65528, 262144, 0, -131064, 65536, 9, -196600, 65536, 7, -262136, 131072, 5, -327672, 131072, 10, -393208, 0, 1, -458744, 65536, 5, -524280, 327680, 5, -589816, 131072, 8, -655352, 0, 0, -720888, 262144, 9, 720903, 196608, 10, 655367, 196608, 0, 589831, 0, 3, 524295, 327680, 3, 458759, 131072, 5, 393223, 262144, 8, 327687, 65536, 5, 262151, 0, 0, 196615, 131072, 0, 131079, 65536, 7, 65543, 262144, 7, 7, 327680, 0, -65529, 327680, 5, -131065, 65536, 0, -196601, 65536, 7, -262137, 196608, 0, -327673, 327680, 1, -393209, 0, 4, -458745, 0, 0, -524281, 131072, 8, -589817, 327680, 4, -655353, 0, 5, -720889, 196608, 10, 720902, 65536, 0, 655366, 0, 5, 589830, 0, 4, 524294, 0, 4, 458758, 131072, 8, 393222, 196608, 0, 327686, 196608, 0, 262150, 327680, 3, 196614, 196608, 9, 131078, 131072, 9, 65542, 327680, 3, 6, 0, 2, -65530, 0, 0, -131066, 131072, 5, -196602, 0, 1, -262138, 327680, 2, -327674, 131072, 5, -393210, 131072, 8, -458746, 262144, 5, -524282, 327680, 0, -589818, 65536, 10, -655354, 196608, 7, -720890, 262144, 8, 720901, 262144, 9, 655365, 0, 2, 589829, 65536, 9, 524293, 0, 2, 458757, 262144, 8, 393221, 327680, 5, 327685, 196608, 0, 262149, 65536, 10, 196613, 327680, 2, 131077, 0, 4, 65541, 131072, 5, 5, 327680, 1, -65531, 131072, 5, -131067, 131072, 9, -196603, 262144, 7, -262139, 65536, 8, -327675, 196608, 0, -393211, 65536, 10, -458747, 65536, 8, -524283, 196608, 9, -589819, 327680, 2, -655355, 0, 4, -720891, 131072, 9, 720900, 131072, 0, 655364, 262144, 0, 589828, 131072, 10, 524292, 0, 1, 458756, 327680, 0, 393220, 0, 1, 327684, 65536, 0, 262148, 262144, 10, 196612, 262144, 10, 131076, 131072, 8, 65540, 0, 4, 4, 65536, 7, -65532, 262144, 5, -131068, 196608, 0, -196604, 262144, 8, -262140, 0, 1, -327676, 131072, 10, -393212, 131072, 7, -458748, 0, 1, -524284, 0, 4, -589820, 0, 1, -655356, 65536, 5, -720892, 0, 0, 720899, 327680, 0, 655363, 327680, 1, 589827, 262144, 10, 524291, 196608, 8, 458755, 327680, 3, 393219, 262144, 0, 327683, 262144, 8, 262147, 262144, 7, 196611, 131072, 0, 131075, 262144, 7, 65539, 327680, 2, 3, 65536, 0, -65533, 131072, 0, -131069, 196608, 7, -196605, 196608, 9, -262141, 65536, 9, -327677, 262144, 7, -393213, 262144, 10, -458749, 196608, 5, -524285, 327680, 3, -589821, 131072, 7, -655357, 196608, 8, -720893, 65536, 10, 720898, 65536, 10, 655362, 65536, 7, 589826, 131072, 8, 524290, 196608, 8, 458754, 196608, 10, 393218, 65536, 8, 327682, 327680, 2, 262146, 0, 5, 196610, 196608, 5, 131074, 262144, 4, 65538, 0, 9, 2, 262144, 3, -65534, 262144, 3, -131070, 262144, 3, -196606, 262144, 1, -262142, 262144, 9, -327678, 262144, 5, -393214, 196608, 9, -458750, 327680, 5, -524286, 327680, 5, -589822, 196608, 8, -655358, 327680, 2, -720894, 131072, 9, 720897, 262144, 7, 655361, 196608, 10, 589825, 262144, 7, 524289, 65536, 8, 458753, 262144, 9, 393217, 65536, 8, 327681, 262144, 9, 262145, 131072, 5, 196609, 196608, 7, 131073, 65536, 6, 65537, 196608, 2, 1, 196608, 3, -65535, 131072, 3, -131071, 196608, 3, -196607, 131072, 11, -262143, 0, 5, -327679, 131072, 10, -393215, 196608, 8, -458751, 327680, 5, -524287, 0, 2, -589823, 196608, 9, -655359, 327680, 0, -720895, 65536, 10, 720896, 0, 4, 655360, 262144, 8, 589824, 327680, 4, 524288, 131072, 0, 458752, 262144, 0, 393216, 0, 1, 327680, 0, 1, 262144, 196608, 9, 196608, 0, 2, 131072, 196608, 6, 65536, 196608, 2, 0, 131072, 3, -65536, 131072, 2, -131072, 196608, 2, -196608, 196608, 11, -262144, 0, 3, -327680, 0, 0, -393216, 65536, 0, -458752, 196608, 9, -524288, 196608, 0, -589824, 196608, 0, -655360, 327680, 2, -720896, 65536, 7, 786431, 0, 3, 720895, 65536, 7, 655359, 0, 4, 589823, 196608, 7, 524287, 196608, 7, 458751, 65536, 9, 393215, 327680, 4, 327679, 65536, 9, 262143, 65536, 8, 196607, 196608, 4, 131071, 131072, 2, 65535, 196608, 3, -1, 131072, 3, -65537, 196608, 2, -131073, 131072, 11, -196609, 262144, 7, -262145, 0, 1, -327681, 65536, 8, -393217, 327680, 1, -458753, 65536, 8, -524289, 131072, 8, -589825, 131072, 9, -655361, 327680, 0, 786430, 65536, 7, 720894, 327680, 4, 655358, 0, 0, 589822, 0, 2, 524286, 262144, 5, 458750, 131072, 0, 393214, 0, 0, 327678, 0, 5, 262142, 196608, 0, 196606, 262144, 6, 131070, 196608, 2, 65534, 196608, 3, -2, 196608, 3, -65538, 131072, 2, -131074, 196608, 1, -196610, 0, 2, -262146, 327680, 5, -327682, 327680, 4, -393218, 131072, 9, -458754, 65536, 9, -524290, 0, 4, -589826, 131072, 5, -655362, 65536, 5, 786429, 196608, 7, 720893, 65536, 9, 655357, 196608, 7, 589821, 327680, 3, 524285, 65536, 10, 458749, 327680, 4, 393213, 262144, 7, 327677, 0, 3, 262141, 196608, 8, 196605, 65536, 4, 131069, 327680, 7, 65533, 65536, 2, -3, 65536, 3, -65539, 327680, 9, -131075, 65536, 1, -196611, 262144, 10, -262147, 196608, 8, -327683, 65536, 7, -393219, 262144, 5, -458755, 262144, 7, -524291, 196608, 5, -589827, 65536, 7, -655363, 196608, 7, 786428, 131072, 5, 720892, 131072, 0, 655356, 196608, 9, 589820, 0, 1, 524284, 65536, 10, 458748, 0, 5, 393212, 262144, 5, 327676, 262144, 5, 262140, 131072, 0, 196604, 0, 3, 131068, 196608, 0, 65532, 327680, 3, -4, 0, 1, -65540, 0, 5, -131076, 327680, 0, -196612, 196608, 9, -262148, 0, 4, -327684, 196608, 9, -393220, 0, 5, -458756, 327680, 2, -524292, 65536, 0, -589828, 0, 5, -655364, 327680, 3, 786427, 196608, 10, 720891, 262144, 5, 655355, 65536, 0, 589819, 131072, 9, 524283, 262144, 0, 458747, 0, 4, 393211, 131072, 0, 327675, 131072, 5, 262139, 327680, 2, 196603, 131072, 7, 131067, 0, 1, 65531, 327680, 3, -5, 65536, 0, -65541, 0, 2, -131077, 196608, 5, -196613, 327680, 1, -262149, 0, 0, -327685, 327680, 5, -393221, 65536, 0, -458757, 327680, 5, -524293, 327680, 1, -589829, 65536, 5, -655365, 262144, 8, 786426, 327680, 3, 720890, 327680, 4, 655354, 65536, 0, 589818, 327680, 5, 524282, 196608, 5, 458746, 262144, 5, 393210, 0, 3, 327674, 196608, 9, 262138, 65536, 0, 196602, 131072, 10, 131066, 0, 1, 65530, 196608, 9, -6, 0, 3, -65542, 0, 4, -131078, 196608, 5, -196614, 65536, 0, -262150, 262144, 5, -327686, 0, 3, -393222, 0, 3, -458758, 196608, 8, -524294, 0, 4, -589830, 262144, 10, -655366, 196608, 0, 786425, 196608, 7, 720889, 262144, 0, 655353, 196608, 0, 589817, 262144, 9, 524281, 0, 1, 458745, 262144, 8, 393209, 327680, 5, 327673, 327680, 0, 262137, 196608, 8, 196601, 131072, 9, 131065, 196608, 8, 65529, 131072, 7, -7, 327680, 0, -65543, 327680, 0, -131079, 0, 1, -196615, 196608, 8, -262151, 65536, 9, -327687, 196608, 5, -393223, 0, 5, -458759, 262144, 10, -524295, 65536, 8, -589831, 65536, 9, -655367, 0, 5, 786424, 196608, 8, 720888, 0, 0, 655352, 262144, 9, 589816, 327680, 4, 524280, 0, 4, 458744, 196608, 9, 393208, 327680, 2, 327672, 0, 2, 262136, 65536, 0, 196600, 0, 1, 131064, 0, 0, 65528, 131072, 0, -8, 0, 0, -65544, 131072, 9, -131080, 131072, 8, -196616, 131072, 0, -262152, 196608, 5, -327688, 131072, 10, -393224, 0, 0, -458760, 0, 5, -524296, 65536, 7, -589832, 131072, 5, -655368, 262144, 7, 786423, 196608, 8, 720887, 327680, 2, 655351, 196608, 9, 589815, 196608, 5, 524279, 131072, 10, 458743, 262144, 8, 393207, 196608, 10, 327671, 65536, 0, 262135, 262144, 10, 196599, 196608, 9, 131063, 131072, 9, 65527, 131072, 5, -9, 131072, 8, -65545, 262144, 9, -131081, 131072, 8, -196617, 65536, 5, -262153, 262144, 8, -327689, 0, 5, -393225, 327680, 3, -458761, 65536, 9, -524297, 327680, 1, -589833, 0, 4, -655369, 0, 1, 786422, 65536, 0, 720886, 196608, 10, 655350, 262144, 5, 589814, 196608, 10, 524278, 262144, 10, 458742, 131072, 5, 393206, 0, 4, 327670, 262144, 7, 262134, 65536, 8, 196598, 327680, 4, 131062, 327680, 3, 65526, 327680, 4, -10, 196608, 8, -65546, 131072, 8, -131082, 131072, 10, -196618, 262144, 5, -262154, 327680, 2, -327690, 131072, 7, -393226, 65536, 5, -458762, 327680, 0, -524298, 131072, 10, -589834, 327680, 0, -655370, 196608, 7, 786421, 196608, 8, 720885, 196608, 7, 655349, 327680, 0, 589813, 196608, 7, 524277, 0, 3, 458741, 327680, 3, 393205, 0, 5, 327669, 131072, 10, 262133, 262144, 9, 196597, 262144, 7, 131061, 65536, 0, 65525, 131072, 7, -11, 0, 4, -65547, 65536, 5, -131083, 131072, 5, -196619, 0, 4, -262155, 327680, 5, -327691, 131072, 0, -393227, 0, 3, -458763, 327680, 1, -524299, 0, 2, -589835, 262144, 10, -655371, 262144, 7, 786420, 65536, 8, 720884, 131072, 8, 655348, 0, 1, 589812, 131072, 10, 524276, 327680, 4, 458740, 0, 0, 393204, 65536, 10, 327668, 131072, 7, 262132, 0, 4, 196596, 327680, 5, 131060, 0, 0, 65524, 0, 0, -12, 131072, 5, -65548, 327680, 1, -131084, 65536, 0, -196620, 196608, 0, -262156, 65536, 10, -327692, 65536, 8, -393228, 65536, 10, -458764, 196608, 8, -524300, 262144, 10, -589836, 0, 5, -655372, 327680, 2, 786419, 262144, 7, 720883, 65536, 9, 655347, 196608, 8, 589811, 196608, 5, 524275, 131072, 9, 458739, 327680, 4, 393203, 0, 0, 327667, 65536, 9, 262131, 327680, 1, 196595, 65536, 5, 131059, 131072, 9, 65523, 196608, 7, -13, 262144, 9, -65549, 196608, 8, -131085, 196608, 8, -196621, 65536, 8, -262157, 262144, 5, -327693, 196608, 9, -393229, 131072, 7, -458765, 262144, 7, -524301, 327680, 3, -589837, 196608, 7, -655373, 196608, 0, 786418, 131072, 5, 720882, 327680, 3, 655346, 327680, 1, 589810, 327680, 0, 524274, 0, 0, 458738, 196608, 10, 393202, 262144, 10, 327666, 327680, 3, 262130, 65536, 9, 196594, 0, 5, 131058, 327680, 1, 65522, 327680, 5, -14, 0, 4, -65550, 65536, 9, -131086, 327680, 5, -196622, 65536, 5, -262158, 131072, 8, -327694, 65536, 5, -393230, 327680, 5, -458766, 262144, 10, -524302, 196608, 5, -589838, 131072, 0, -655374, 196608, 0, 786417, 262144, 8, 720881, 327680, 2, 655345, 327680, 4, 589809, 262144, 0, 524273, 262144, 9, 458737, 196608, 7, 393201, 262144, 5, 327665, 0, 1, 262129, 65536, 10, 196593, 0, 5, 131057, 65536, 9, 65521, 196608, 5, -15, 131072, 7, -65551, 262144, 0, -131087, 65536, 5, -196623, 65536, 8, -262159, 327680, 4, -327695, 196608, 0, -393231, 131072, 7, -458767, 262144, 9, -524303, 65536, 7, -589839, 262144, 8, -655375, 262144, 9, 786416, 65536, 0, 720880, 196608, 8, 655344, 0, 0, 589808, 131072, 7, 524272, 196608, 9, 458736, 0, 3, 393200, 327680, 1, 327664, 327680, 4, 262128, 131072, 9, 196592, 131072, 10, 131056, 262144, 0, 65520, 131072, 5, -16, 65536, 7, -65552, 327680, 4, -131088, 0, 4, -196624, 262144, 10, -262160, 327680, 0, -327696, 196608, 0, -393232, 65536, 8, -458768, 262144, 0, -524304, 196608, 9, -589840, 196608, 5, -655376, 0, 3, 786415, 262144, 0, 720879, 0, 2, 655343, 196608, 8, 589807, 65536, 5, 524271, 262144, 5, 458735, 327680, 1, 393199, 0, 2, 327663, 65536, 10, 262127, 196608, 5, 196591, 262144, 7, 131055, 0, 3, 65519, 262144, 5, -17, 0, 1, -65553, 262144, 10, -131089, 65536, 10, -196625, 196608, 5, -262161, 131072, 0, -327697, 327680, 5, -393233, 65536, 0, -458769, 65536, 5, -524305, 262144, 8, -589841, 196608, 0, -655377, 327680, 5, 786414, 0, 0, 720878, 131072, 0, 655342, 131072, 10, 589806, 65536, 7, 524270, 65536, 5, 458734, 0, 2, 393198, 131072, 7, 327662, 131072, 10, 262126, 196608, 0, 196590, 196608, 8, 131054, 65536, 8, 65518, 327680, 2, -18, 65536, 0, -65554, 196608, 0, -131090, 327680, 3, -196626, 196608, 0, -262162, 131072, 8, -327698, 262144, 5, -393234, 327680, 5, -458770, 262144, 5, -524306, 131072, 0, -589842, 327680, 0, -655378, 262144, 5, 786413, 262144, 5, 720877, 65536, 0, 655341, 196608, 0, 589805, 196608, 10, 524269, 196608, 9, 458733, 262144, 9, 393197, 0, 4, 327661, 196608, 5, 262125, 196608, 0, 196589, 65536, 0, 131053, 0, 2, 65517, 196608, 9, -19, 262144, 5, -65555, 131072, 5, -131091, 327680, 2, -196627, 327680, 4, -262163, 131072, 8, -327699, 65536, 9, -393235, 0, 4, -458771, 0, 4, -524307, 0, 4, -589843, 327680, 3, -655379, 196608, 9, 786412, 65536, 7, 720876, 0, 3, 655340, 65536, 10, 589804, 0, 4, 524268, 0, 4, 458732, 262144, 9, 393196, 131072, 5, 327660, 327680, 1, 262124, 262144, 7, 196588, 65536, 9, 131052, 262144, 10, 65516, 0, 5, -20, 327680, 0, -65556, 327680, 0, -131092, 65536, 9, -196628, 196608, 7, -262164, 262144, 9, -327700, 0, 2, -393236, 196608, 8, -458772, 262144, 9, -524308, 262144, 7, -589844, 262144, 5, -655380, 196608, 8, -786413, 65536, 8, -786414, 131072, 0, -786415, 327680, 5, -786416, 327680, 2, -786417, 65536, 0, -786418, 65536, 8, -786419, 327680, 0, -786420, 0, 3, -786421, 327680, 5, -786422, 65536, 9, -786423, 65536, 7, -786424, 0, 3, -786425, 262144, 5, -786426, 196608, 8, -786427, 65536, 10, -786428, 131072, 8, -786429, 0, 1, -786430, 262144, 5, -786431, 65536, 10, -786432, 327680, 4, -720897, 262144, 8, -720898, 327680, 1, -720899, 196608, 9, -720900, 65536, 5, -720901, 262144, 9, -720902, 327680, 5, -720903, 196608, 0, -720904, 327680, 3, -720905, 327680, 2, -720906, 262144, 10, -720907, 262144, 10, -720908, 0, 2, -720909, 65536, 10, -720910, 262144, 7, -720911, 0, 2, -720912, 327680, 1, -720913, 0, 0, -720914, 131072, 9, -720915, 262144, 8, -720916, 65536, 0)
[node name="GameCamera" parent="." instance=ExtResource("2_db5xs")]
-[node name="CursorMagnet" parent="." instance=ExtResource("3_xbolm")]
+[node name="Cursor" parent="." instance=ExtResource("5_g504x")]
-[node name="GoldCounter" parent="." instance=ExtResource("3_p6jw3")]
+[node name="Walls" type="Node2D" parent="."]
-[node name="SpawnedEntities" type="Node2D" parent="."]
+[node name="BottomBoundary" type="StaticBody2D" parent="Walls"]
+position = Vector2(0, 360)
+collision_layer = 2
+collision_mask = 0
-[node name="Node2D" type="Node2D" parent="."]
-position = Vector2(590, 317)
-scale = Vector2(11.285, 11.285)
+[node name="Shape" type="CollisionShape2D" parent="Walls/BottomBoundary"]
+shape = SubResource("WorldBoundaryShape2D_htttx")
-[node name="Sprite2D" type="Sprite2D" parent="Node2D"]
-scale = Vector2(0.03, 0.029)
-texture = ExtResource("9_8kxq4")
+[node name="TopBoundary" type="StaticBody2D" parent="Walls"]
+position = Vector2(0, -360)
+rotation = 3.14159
+collision_layer = 2
+collision_mask = 0
-[node name="Area2D" type="Area2D" parent="Node2D"]
+[node name="Shape" type="CollisionShape2D" parent="Walls/TopBoundary"]
+shape = SubResource("WorldBoundaryShape2D_htttx")
-[node name="CollisionShape2D" type="CollisionShape2D" parent="Node2D/Area2D"]
-scale = Vector2(0.0886132, 0.0886132)
-shape = SubResource("CircleShape2D_3du4x")
+[node name="RightBoundary" type="StaticBody2D" parent="Walls"]
+position = Vector2(640, 0)
+rotation = 4.71239
+collision_layer = 2
+collision_mask = 0
-[node name="Imp" parent="." instance=ExtResource("10_26rf6")]
-position = Vector2(-275, 10)
+[node name="Shape" type="CollisionShape2D" parent="Walls/RightBoundary"]
+shape = SubResource("WorldBoundaryShape2D_htttx")
-[connection signal="mouse_entered" from="Node2D/Area2D" to="CloudSpawner" method="spawn"]
+[node name="LeftBoundary" type="StaticBody2D" parent="Walls"]
+position = Vector2(-640, 0)
+rotation = 1.5708
+collision_layer = 2
+collision_mask = 0
+
+[node name="Shape" type="CollisionShape2D" parent="Walls/LeftBoundary"]
+shape = SubResource("WorldBoundaryShape2D_htttx")
+
+[node name="DefaultSpawnParent" type="Node2D" parent="."]
+unique_name_in_owner = true
+
+[node name="Skull" parent="." instance=ExtResource("6_5k7gy")]
+position = Vector2(2, 3)
+
+[node name="Monocle" parent="." instance=ExtResource("7_lahut")]
+position = Vector2(-56, 56)
+
+[node name="TopHat" parent="." instance=ExtResource("8_atoon")]
+position = Vector2(56, -50)
+
+[node name="Sheep" parent="." instance=ExtResource("9_qrqqu")]
+position = Vector2(-310, 166)
+
+[node name="Imp" parent="." instance=ExtResource("10_yw228")]
+position = Vector2(393, -137)
+
+[node name="Sheep2" parent="." instance=ExtResource("9_qrqqu")]
+position = Vector2(-415, 202)
+
+[node name="Sheep3" parent="." instance=ExtResource("9_qrqqu")]
+position = Vector2(-386, 112)
+
+[node name="Sheep4" parent="." instance=ExtResource("9_qrqqu")]
+position = Vector2(-314, 261)
+
+[node name="Sheep5" parent="." instance=ExtResource("9_qrqqu")]
+position = Vector2(-211, 241)
+
+[node name="Sheep6" parent="." instance=ExtResource("9_qrqqu")]
+position = Vector2(-491, 137)
+
+[node name="Sheep7" parent="." instance=ExtResource("9_qrqqu")]
+position = Vector2(-177, 154)
diff --git a/temp/gore.wav b/temp/gore.wav
deleted file mode 100644
index 681e56b..0000000
--- a/temp/gore.wav
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:263e85a80630a5123045cdfed923a51248471fdf07f558383e2dff5b709cbd82
-size 966522
diff --git a/temp/gore.wav.import b/temp/gore.wav.import
deleted file mode 100644
index 59719b5..0000000
--- a/temp/gore.wav.import
+++ /dev/null
@@ -1,24 +0,0 @@
-[remap]
-
-importer="wav"
-type="AudioStreamWAV"
-uid="uid://dlp0oo8tbp3w1"
-path="res://.godot/imported/gore.wav-c74757bf12b5b41aaaf2eb9a0f1110a0.sample"
-
-[deps]
-
-source_file="res://temp/gore.wav"
-dest_files=["res://.godot/imported/gore.wav-c74757bf12b5b41aaaf2eb9a0f1110a0.sample"]
-
-[params]
-
-force/8_bit=false
-force/mono=false
-force/max_rate=false
-force/max_rate_hz=44100
-edit/trim=false
-edit/normalize=false
-edit/loop_mode=0
-edit/loop_begin=0
-edit/loop_end=-1
-compress/mode=0
diff --git a/traversal.gd b/traversal.gd
new file mode 100644
index 0000000..f9ba9d6
--- /dev/null
+++ b/traversal.gd
@@ -0,0 +1,11 @@
+class_name Traversal
+
+
+## Get the first possible [MainGame] instance by climbing the scene tree one ancestor at a time.
+static func get_ancestors(start: Node) -> Array[Node]:
+ var result: Array[Node] = []
+ var current = start
+ while current is Node:
+ result.push_back(current)
+ current = current.get_parent()
+ return result