Merge pull request #1 from Steffo99/feature/componentized-behaviours
Refactor everything into componentized and reusable behaviours
18
.vscode/launch.json
vendored
Normal file
|
@ -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}",
|
||||
}
|
||||
]
|
||||
}
|
10
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 |
|
||||
|
|
|
@ -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])
|
|
@ -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"]
|
17
behaviours/collectible.gd
Normal file
|
@ -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)
|
|
@ -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 @@
|
|||
<path
|
||||
d="M 288,32 C 288,14.3 273.7,0 256,0 238.3,0 224,14.3 224,32 v 208 c 0,8.8 -7.2,16 -16,16 -8.8,0 -16,-7.2 -16,-16 V 64 c 0,-17.7 -14.3,-32 -32,-32 -17.7,0 -32,14.3 -32,32 v 272 c 0,1.5 0,3.1 0.1,4.6 L 67.6,283 c -16,-15.2 -41.3,-14.6 -56.6,1.4 -15.3,16 -14.6,41.3 1.4,56.6 l 112.4,107 c 43.1,41.1 100.4,64 160,64 H 304 c 97.2,0 176,-78.8 176,-176 V 128 c 0,-17.7 -14.3,-32 -32,-32 -17.7,0 -32,14.3 -32,32 v 112 c 0,8.8 -7.2,16 -16,16 -8.8,0 -16,-7.2 -16,-16 V 64 c 0,-17.7 -14.3,-32 -32,-32 -17.7,0 -32,14.3 -32,32 v 176 c 0,8.8 -7.2,16 -16,16 -8.8,0 -16,-7.2 -16,-16 z"
|
||||
id="path1"
|
||||
style="fill:#8da5f3;fill-opacity:1" />
|
||||
style="fill:#e0e0e0;fill-opacity:1" />
|
||||
</svg>
|
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.9 KiB |
|
@ -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]
|
||||
|
6
behaviours/collectible.tscn
Normal file
|
@ -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")
|
24
behaviours/cursor_detector.gd
Normal file
|
@ -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)
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.6 KiB |
|
@ -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]
|
||||
|
13
behaviours/cursor_detector.tscn
Normal file
|
@ -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"]
|
|
@ -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)
|
||||
|
|
39
behaviours/draggable.svg
Normal file
|
@ -0,0 +1,39 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
viewBox="0 0 512 512"
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
sodipodi:docname="draggable.svg"
|
||||
inkscape:version="1.3.2 (091e20ef0f, 2023-11-25, custom)"
|
||||
width="16"
|
||||
height="16"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs1" />
|
||||
<sodipodi:namedview
|
||||
id="namedview1"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
inkscape:zoom="1.6464844"
|
||||
inkscape:cx="217.1293"
|
||||
inkscape:cy="209.84104"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1020"
|
||||
inkscape:window-x="3200"
|
||||
inkscape:window-y="32"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg1" />
|
||||
<!--! Font Awesome Free 6.5.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc. -->
|
||||
<path
|
||||
d="m 278.6,9.4 c -12.5,-12.5 -32.8,-12.5 -45.3,0 l -64,64 c -12.5,12.5 -12.5,32.8 0,45.3 12.5,12.5 32.8,12.5 45.3,0 l 9.4,-9.4 V 224 H 109.3 l 9.4,-9.4 c 12.5,-12.5 12.5,-32.8 0,-45.3 -12.5,-12.5 -32.8,-12.5 -45.3,0 l -64,64 c -12.5,12.5 -12.5,32.8 0,45.3 l 64,64 c 12.5,12.5 32.8,12.5 45.3,0 12.5,-12.5 12.5,-32.8 0,-45.3 l -9.4,-9.4 H 224 v 114.8 l -9.4,-9.4 c -12.5,-12.5 -32.8,-12.5 -45.3,0 -12.5,12.5 -12.5,32.8 0,45.3 l 64,64 c 12.5,12.5 32.8,12.5 45.3,0 l 64,-64 c 12.5,-12.5 12.5,-32.8 0,-45.3 -12.5,-12.5 -32.8,-12.5 -45.3,0 l -9.4,9.4 V 288 h 114.8 l -9.4,9.4 c -12.5,12.5 -12.5,32.8 0,45.3 12.5,12.5 32.8,12.5 45.3,0 l 64,-64 c 12.5,-12.5 12.5,-32.8 0,-45.3 l -64,-64 c -12.5,-12.5 -32.8,-12.5 -45.3,0 -12.5,12.5 -12.5,32.8 0,45.3 l 9.4,9.4 H 288 V 109.3 l 9.4,9.4 c 12.5,12.5 32.8,12.5 45.3,0 12.5,-12.5 12.5,-32.8 0,-45.3 l -64,-64 z"
|
||||
id="path1"
|
||||
style="fill:#8da5f3" />
|
||||
</svg>
|
After Width: | Height: | Size: 2.1 KiB |
|
@ -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]
|
||||
|
|
@ -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"]
|
||||
|
|
|
@ -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)
|
|
@ -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"]
|
|
@ -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)
|
||||
|
|
|
@ -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"]
|
||||
|
|
|
@ -14,6 +14,3 @@ signal eaten
|
|||
|
||||
func eat():
|
||||
eaten.emit()
|
||||
|
||||
func _on_eaten() -> void:
|
||||
Log.p(self, "Got eaten.")
|
||||
|
|
|
@ -4,5 +4,3 @@
|
|||
|
||||
[node name="Edible" type="Node"]
|
||||
script = ExtResource("1_l6vtr")
|
||||
|
||||
[connection signal="eaten" from="." to="." method="_on_eaten"]
|
||||
|
|
|
@ -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)
|
|
@ -1,39 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
viewBox="0 0 512 512"
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
sodipodi:docname="bowl-rice.svg"
|
||||
inkscape:version="1.3.2 (091e20ef0f, 2023-11-25, custom)"
|
||||
width="16"
|
||||
height="16"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs1" />
|
||||
<sodipodi:namedview
|
||||
id="namedview1"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
inkscape:zoom="1.6464844"
|
||||
inkscape:cx="256"
|
||||
inkscape:cy="256"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1020"
|
||||
inkscape:window-x="1280"
|
||||
inkscape:window-y="32"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg1" />
|
||||
<!--! Font Awesome Free 6.5.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc. -->
|
||||
<path
|
||||
d="m 176,56 c 0,-13.3 10.7,-24 24,-24 h 16 c 13.3,0 24,10.7 24,24 0,13.3 -10.7,24 -24,24 H 200 C 186.7,80 176,69.3 176,56 Z m 24,48 h 16 c 13.3,0 24,10.7 24,24 0,13.3 -10.7,24 -24,24 h -16 c -13.3,0 -24,-10.7 -24,-24 0,-13.3 10.7,-24 24,-24 z M 56,176 h 16 c 13.3,0 24,10.7 24,24 0,13.3 -10.7,24 -24,24 H 56 C 42.7,224 32,213.3 32,200 32,186.7 42.7,176 56,176 Z M 0,283.4 C 0,268.3 12.3,256 27.4,256 h 457.2 c 15.1,0 27.4,12.3 27.4,27.4 0,70.5 -44.4,130.7 -106.7,154.1 l -1.8,14.5 c -2,16 -15.6,28 -31.8,28 H 140.2 c -16.1,0 -29.8,-12 -31.8,-28 l -1.8,-14.4 C 44.4,414.1 0,353.9 0,283.4 Z M 224,200 c 0,-13.3 10.7,-24 24,-24 h 16 c 13.3,0 24,10.7 24,24 0,13.3 -10.7,24 -24,24 h -16 c -13.3,0 -24,-10.7 -24,-24 z m -96,0 c 0,-13.3 10.7,-24 24,-24 h 16 c 13.3,0 24,10.7 24,24 0,13.3 -10.7,24 -24,24 h -16 c -13.3,0 -24,-10.7 -24,-24 z m -24,-96 h 16 c 13.3,0 24,10.7 24,24 0,13.3 -10.7,24 -24,24 h -16 c -13.3,0 -24,-10.7 -24,-24 0,-13.3 10.7,-24 24,-24 z m 216,96 c 0,-13.3 10.7,-24 24,-24 h 16 c 13.3,0 24,10.7 24,24 0,13.3 -10.7,24 -24,24 h -16 c -13.3,0 -24,-10.7 -24,-24 z m -24,-96 h 16 c 13.3,0 24,10.7 24,24 0,13.3 -10.7,24 -24,24 h -16 c -13.3,0 -24,-10.7 -24,-24 0,-13.3 10.7,-24 24,-24 z m 120,96 c 0,-13.3 10.7,-24 24,-24 h 16 c 13.3,0 24,10.7 24,24 0,13.3 -10.7,24 -24,24 h -16 c -13.3,0 -24,-10.7 -24,-24 z m -24,-96 h 16 c 13.3,0 24,10.7 24,24 0,13.3 -10.7,24 -24,24 h -16 c -13.3,0 -24,-10.7 -24,-24 0,-13.3 10.7,-24 24,-24 z M 296,32 h 16 c 13.3,0 24,10.7 24,24 0,13.3 -10.7,24 -24,24 h -16 c -13.3,0 -24,-10.7 -24,-24 0,-13.3 10.7,-24 24,-24 z"
|
||||
id="path1"
|
||||
style="fill:#8da5f3" />
|
||||
</svg>
|
Before Width: | Height: | Size: 2.8 KiB |
|
@ -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"]
|
|
@ -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
|
|
@ -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"]
|
|
@ -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)
|
|
@ -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"]
|
22
behaviours/move.gd
Normal file
|
@ -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()
|
39
behaviours/move.svg
Normal file
|
@ -0,0 +1,39 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
viewBox="0 0 512 512"
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
sodipodi:docname="move_towards.svg"
|
||||
width="16"
|
||||
height="16"
|
||||
inkscape:version="1.3.2 (091e20ef0f, 2023-11-25, custom)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs1" />
|
||||
<sodipodi:namedview
|
||||
id="namedview1"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
inkscape:zoom="1.6464844"
|
||||
inkscape:cx="223.8102"
|
||||
inkscape:cy="236.56465"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1020"
|
||||
inkscape:window-x="1280"
|
||||
inkscape:window-y="32"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg1" />
|
||||
<!--! Font Awesome Free 6.5.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc. -->
|
||||
<path
|
||||
d="m 470.6125,278.6 c 12.5,-12.5 12.5,-32.8 0,-45.3 l -160,-160 c -12.5,-12.5 -32.8,-12.5 -45.3,0 -12.5,12.5 -12.5,32.8 0,45.3 l 105.5,105.4 h -306.8 c -17.7,0 -32,14.3 -32,32 0,17.7 14.3,32 32,32 h 306.7 l -105.3,105.4 c -12.5,12.5 -12.5,32.8 0,45.3 12.5,12.5 32.8,12.5 45.3,0 l 160,-160 z"
|
||||
id="path1"
|
||||
style="fill:#8da5f3" />
|
||||
</svg>
|
After Width: | Height: | Size: 1.6 KiB |
37
behaviours/move.svg.import
Normal file
|
@ -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
|
46
behaviours/move_physics.gd
Normal file
|
@ -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)
|
6
behaviours/move_physics.tscn
Normal file
|
@ -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")
|
35
behaviours/move_straight.gd
Normal file
|
@ -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)
|
6
behaviours/move_straight.tscn
Normal file
|
@ -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")
|
|
@ -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)
|
||||
|
|
6
behaviours/move_towards.tscn
Normal file
|
@ -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")
|
|
@ -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()
|
||||
|
|
@ -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"]
|
|
@ -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)
|
|
@ -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")
|
69
behaviours/priority.gd
Normal file
|
@ -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
|
39
behaviours/priority.svg
Normal file
|
@ -0,0 +1,39 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
viewBox="0 0 575.99539 575.99537"
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
sodipodi:docname="priority.svg"
|
||||
width="16"
|
||||
height="16"
|
||||
inkscape:version="1.3.2 (091e20ef0f, 2023-11-25, custom)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs1" />
|
||||
<sodipodi:namedview
|
||||
id="namedview1"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
inkscape:zoom="1.6464844"
|
||||
inkscape:cx="287.88612"
|
||||
inkscape:cy="248.71174"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1020"
|
||||
inkscape:window-x="1280"
|
||||
inkscape:window-y="32"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg1" />
|
||||
<!--! Font Awesome Free 6.5.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc. -->
|
||||
<path
|
||||
d="m 316.72587,49.969031 c -5.3,-11 -16.5,-18 -28.8,-18 -12.3,0 -23.4,7 -28.8,18 l -64.3,132.299999 -143.600005,21.2 c -12,1.8 -22,10.2 -25.7,21.7 -3.7,11.5 -0.7,24.2 7.9,32.7 l 104.200005,103.1 -24.6,145.7 c -2,12 3,24.2 12.9,31.3 9.9,7.1 23,8 33.8,2.3 l 128.3,-68.5 128.3,68.5 c 10.8,5.7 23.9,4.9 33.8,-2.3 9.9,-7.2 14.9,-19.3 12.9,-31.3 l -24.7,-145.7 104.2,-103.1 c 8.6,-8.5 11.7,-21.2 7.9,-32.7 -3.8,-11.5 -13.7,-19.9 -25.7,-21.7 l -143.7,-21.2 z"
|
||||
id="path1"
|
||||
style="fill:#e0e0e0" />
|
||||
</svg>
|
After Width: | Height: | Size: 1.7 KiB |
37
behaviours/priority.svg.import
Normal file
|
@ -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
|
8
behaviours/priority.tscn
Normal file
|
@ -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"]
|
29
behaviours/sampler.gd
Normal file
|
@ -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
|
59
behaviours/sampler.svg
Normal file
|
@ -0,0 +1,59 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
viewBox="0 0 512 512"
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
sodipodi:docname="sampler.svg"
|
||||
width="16"
|
||||
height="16"
|
||||
inkscape:version="1.3.2 (091e20ef0f, 2023-11-25, custom)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs1" />
|
||||
<sodipodi:namedview
|
||||
id="namedview1"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
inkscape:zoom="13.171875"
|
||||
inkscape:cx="16.778173"
|
||||
inkscape:cy="17.651246"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1020"
|
||||
inkscape:window-x="3200"
|
||||
inkscape:window-y="32"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg1" />
|
||||
<!--! Font Awesome Free 6.5.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc. -->
|
||||
<path
|
||||
d="m 48,368 a 48,48 0 1 1 0,96 48,48 0 1 1 0,-96 z"
|
||||
id="path6"
|
||||
style="fill:#e0e0e0" />
|
||||
<path
|
||||
d="m 160,416 c 0,-17.7 14.3,-32 32,-32 h 288 c 17.7,0 32,14.3 32,32 0,17.7 -14.3,32 -32,32 H 192 c -17.7,0 -32,-14.3 -32,-32 z"
|
||||
id="path5"
|
||||
style="fill:#e0e0e0" />
|
||||
<path
|
||||
d="m 160,256 c 0,-17.7 14.3,-32 32,-32 h 288 c 17.7,0 32,14.3 32,32 0,17.7 -14.3,32 -32,32 H 192 c -17.7,0 -32,-14.3 -32,-32 z"
|
||||
id="path5-7"
|
||||
style="fill:#e0e0e0" />
|
||||
<path
|
||||
d="m 224,96 c 0,-17.7 14.3,-32 32,-32 h 224 c 17.7,0 32,14.3 32,32 0,17.7 -14.3,32 -32,32 H 256 c -17.7,0 -32,-14.3 -32,-32 z"
|
||||
id="path3"
|
||||
style="fill:#e0e0e0" />
|
||||
<path
|
||||
d="m 152.1,38.2 c 9.9,8.9 10.7,24 1.8,33.9 l -72,80 c -4.4,4.9 -10.6,7.8 -17.2,7.9 -6.6,0.1 -12.9,-2.4 -17.6,-7 L 7,113 c -9.3,-9.4 -9.3,-24.6 0,-34 9.3,-9.4 24.6,-9.4 33.9,0 L 63,101.1 118.1,39.9 C 127,30 142.1,29.2 152,38.1 Z"
|
||||
id="path1"
|
||||
style="fill:#8eef97" />
|
||||
<path
|
||||
d="M 96,256 A 48,48 0 1 0 5e-7,256 48,48 0 1 0 96,256 Z"
|
||||
id="path6-5"
|
||||
style="fill:#e0e0e0" />
|
||||
</svg>
|
After Width: | Height: | Size: 2.3 KiB |
37
behaviours/sampler.svg.import
Normal file
|
@ -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
|
28
behaviours/sampler_priority.gd
Normal file
|
@ -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
|
6
behaviours/sampler_priority.tscn
Normal file
|
@ -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")
|
11
behaviours/sampler_random.gd
Normal file
|
@ -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)
|
6
behaviours/sampler_random.tscn
Normal file
|
@ -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")
|
|
@ -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.")
|
6
behaviours/sampler_weighted.tscn
Normal file
|
@ -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")
|
|
@ -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.")
|
|
@ -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"]
|
|
@ -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.
|
||||
|
|
47
behaviours/spawner.svg
Normal file
|
@ -0,0 +1,47 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
viewBox="0 0 640 640"
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
sodipodi:docname="spawner.svg"
|
||||
width="16"
|
||||
height="16"
|
||||
inkscape:version="1.3.2 (091e20ef0f, 2023-11-25, custom)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs1" />
|
||||
<sodipodi:namedview
|
||||
id="namedview1"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
inkscape:zoom="26.34375"
|
||||
inkscape:cx="13.001186"
|
||||
inkscape:cy="9.9264532"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1020"
|
||||
inkscape:window-x="1280"
|
||||
inkscape:window-y="32"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg1" />
|
||||
<!--! Font Awesome Free 6.5.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc. -->
|
||||
<path
|
||||
d="m 504,376 v -64 h -64 c -13.3,0 -24,-10.7 -24,-24 0,-13.3 10.7,-24 24,-24 h 64 v -64 c 0,-13.3 10.7,-24 24,-24 13.3,0 24,10.7 24,24 v 64 h 64 c 13.3,0 24,10.7 24,24 0,13.3 -10.7,24 -24,24 h -64 v 64 c 0,13.3 -10.7,24 -24,24 -13.3,0 -24,-10.7 -24,-24 z"
|
||||
id="path3"
|
||||
style="fill:#73f280;fill-opacity:1" />
|
||||
<path
|
||||
d="M 0,546.3 C 0,447.8 79.8,368 178.3,368 h 91.4 c 98.5,0 178.3,79.8 178.3,178.3 0,16.4 -13.3,29.7 -29.7,29.7 H 29.7 C 13.3,576 0,562.7 0,546.3 Z"
|
||||
id="path2"
|
||||
style="fill:#8da5f3" />
|
||||
<path
|
||||
d="m 96,192 a 128,128 0 1 1 256,0 128,128 0 1 1 -256,0 z"
|
||||
id="path1"
|
||||
style="fill:#8da5f3" />
|
||||
</svg>
|
After Width: | Height: | Size: 1.9 KiB |
37
behaviours/spawner.svg.import
Normal file
|
@ -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
|
|
@ -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")
|
|
@ -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"]
|
48
behaviours/target_picker.gd
Normal file
|
@ -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.
|
39
behaviours/target_picker.svg
Normal file
|
@ -0,0 +1,39 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
viewBox="0 0 512 512"
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
sodipodi:docname="target_picker_random.svg"
|
||||
inkscape:version="1.3.2 (091e20ef0f, 2023-11-25, custom)"
|
||||
width="16"
|
||||
height="16"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs1" />
|
||||
<sodipodi:namedview
|
||||
id="namedview1"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
inkscape:zoom="1.6464844"
|
||||
inkscape:cx="256"
|
||||
inkscape:cy="256"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1020"
|
||||
inkscape:window-x="3200"
|
||||
inkscape:window-y="32"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg1" />
|
||||
<!--! Font Awesome Free 6.5.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc. -->
|
||||
<path
|
||||
d="m 448,256 a 192,192 0 1 0 -384,0 192,192 0 1 0 384,0 z M 0,256 a 256,256 0 1 1 512,0 256,256 0 1 1 -512,0 z m 256,80 a 80,80 0 1 0 0,-160 80,80 0 1 0 0,160 z m 0,-224 a 144,144 0 1 1 0,288 144,144 0 1 1 0,-288 z m -32,144 a 32,32 0 1 1 64,0 32,32 0 1 1 -64,0 z"
|
||||
id="path1"
|
||||
style="fill:#e0e0e0" />
|
||||
</svg>
|
After Width: | Height: | Size: 1.5 KiB |
37
behaviours/target_picker.svg.import
Normal file
|
@ -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
|
6
behaviours/target_picker.tscn
Normal file
|
@ -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")
|
19
behaviours/timer_stddev.gd
Normal file
|
@ -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
|
||||
)
|
8
behaviours/timer_stddev.tscn
Normal file
|
@ -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"]
|
44
behaviours/tracker.gd
Normal file
|
@ -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)
|
39
behaviours/tracker.svg
Normal file
|
@ -0,0 +1,39 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
viewBox="0 0 512 512"
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
sodipodi:docname="tracker.svg"
|
||||
width="16"
|
||||
height="16"
|
||||
inkscape:version="1.3.2 (091e20ef0f, 2023-11-25, custom)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs1" />
|
||||
<sodipodi:namedview
|
||||
id="namedview1"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
inkscape:zoom="8"
|
||||
inkscape:cx="21.0625"
|
||||
inkscape:cy="41.9375"
|
||||
inkscape:window-width="1280"
|
||||
inkscape:window-height="964"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="60"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg1" />
|
||||
<!--! Font Awesome Free 6.5.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc. -->
|
||||
<path
|
||||
d="m 256,0 c 17.7,0 32,14.3 32,32 v 10.4 c 93.7,13.9 167.7,88 181.6,181.6 H 480 c 17.7,0 32,14.3 32,32 0,17.7 -14.3,32 -32,32 H 469.6 C 455.7,381.7 381.6,455.7 288,469.6 V 480 c 0,17.7 -14.3,32 -32,32 -17.7,0 -32,-14.3 -32,-32 V 469.6 C 130.3,455.7 56.3,381.7 42.4,288 H 32 C 14.3,288 0,273.7 0,256 0,238.3 14.3,224 32,224 H 42.4 C 56.3,130.3 130.3,56.3 224,42.4 V 32 C 224,14.3 238.3,0 256,0 Z M 107.4,288 c 12.5,58.3 58.4,104.1 116.6,116.6 V 384 c 0,-17.7 14.3,-32 32,-32 17.7,0 32,14.3 32,32 v 20.6 C 346.3,392.1 392.1,346.2 404.6,288 H 384 c -17.7,0 -32,-14.3 -32,-32 0,-17.7 14.3,-32 32,-32 h 20.6 C 392.1,165.7 346.3,119.9 288,107.4 V 128 c 0,17.7 -14.3,32 -32,32 -17.7,0 -32,-14.3 -32,-32 V 107.4 C 165.7,119.9 119.9,165.7 107.4,224 H 128 c 17.7,0 32,14.3 32,32 0,17.7 -14.3,32 -32,32 z M 256,224 a 32,32 0 1 1 0,64 32,32 0 1 1 0,-64 z"
|
||||
id="path1"
|
||||
style="fill:#699ce8" />
|
||||
</svg>
|
After Width: | Height: | Size: 2.1 KiB |
37
behaviours/tracker.svg.import
Normal file
|
@ -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
|
13
behaviours/tracker.tscn
Normal file
|
@ -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"]
|
15
behaviours/tracker_edible.gd
Normal file
|
@ -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
|
13
behaviours/tracker_edible.tscn
Normal file
|
@ -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"]
|
24
behaviours/tracker_tracker.gd
Normal file
|
@ -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
|
13
behaviours/tracker_tracker.tscn
Normal file
|
@ -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"]
|
BIN
entities/drop.wav
(Stored with Git LFS)
|
@ -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
|
BIN
entities/fall.ogg
(Stored with Git LFS)
Normal file
19
entities/fall.ogg.import
Normal file
|
@ -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
|
|
@ -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()
|
||||
|
|
|
@ -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"]
|
||||
|
|
|
@ -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_draggable_move(movement:Vector2):
|
||||
if draggable.being_dragged:
|
||||
move_and_collide(movement)
|
||||
sprite.handle_move(movement)
|
||||
|
||||
func _on_move(movement: Vector2):
|
||||
if not draggable.being_dragged:
|
||||
move_and_collide(movement)
|
||||
sprite.handle_move(movement)
|
||||
|
||||
func _on_eater_eaten(edible: Edible) -> void:
|
||||
edible.get_parent().queue_free()
|
||||
|
||||
func _on_dragged(_cursor: Cursor) -> void:
|
||||
collision_layer = 16
|
||||
collision_mask = 18
|
||||
z_index = 1
|
||||
eater.collision_mask = 16
|
||||
|
||||
func _on_fallen() -> void:
|
||||
collision_layer = 8
|
||||
collision_mask = 14
|
||||
z_index = 0
|
||||
eater.collision_mask = 8
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -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]
|
||||
|
BIN
entities/imp_eat.ogg
(Stored with Git LFS)
Normal file
19
entities/imp_eat.ogg.import
Normal file
|
@ -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
|
16
entities/monocle.gd
Normal file
|
@ -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
|
|
@ -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]
|
||||
|
49
entities/monocle.tscn
Normal file
|
@ -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"]
|
|
@ -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]
|
||||
|
|
@ -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)
|
||||
|
||||
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
|
||||
|
|
|
@ -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"]
|
||||
|
|
|
@ -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()
|
||||
|
||||
|
16
entities/skull.gd
Normal file
|
@ -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
|
|
@ -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]
|
||||
|