summaryrefslogtreecommitdiff
path: root/Scenes/Entities/Enemies
diff options
context:
space:
mode:
authorDaniel Weipert <git@mail.dweipert.de>2024-04-27 20:06:49 +0200
committerDaniel Weipert <git@mail.dweipert.de>2024-04-27 20:06:49 +0200
commit81cc6f1d22677dd4a60aa9377c91b291bf10e523 (patch)
tree9c22712a9746ed0598a44be6e88727d021436860 /Scenes/Entities/Enemies
parentc8a316e4b8987dad963656a34665fa0e23dedcb1 (diff)
update
Diffstat (limited to 'Scenes/Entities/Enemies')
-rw-r--r--Scenes/Entities/Enemies/Balloon.gd16
-rw-r--r--Scenes/Entities/Enemies/Balloon.tscn22
-rw-r--r--Scenes/Entities/Enemies/Components/Collision.gd11
-rw-r--r--Scenes/Entities/Enemies/Components/Health.gd39
-rw-r--r--Scenes/Entities/Enemies/Components/Health.tscn6
-rw-r--r--Scenes/Entities/Enemies/Components/Movement.gd57
-rw-r--r--Scenes/Entities/Enemies/Slime.gd11
-rw-r--r--Scenes/Entities/Enemies/Slime.tscn68
-rw-r--r--Scenes/Entities/Enemies/Tree.gd22
-rw-r--r--Scenes/Entities/Enemies/Tree.tscn175
10 files changed, 393 insertions, 34 deletions
diff --git a/Scenes/Entities/Enemies/Balloon.gd b/Scenes/Entities/Enemies/Balloon.gd
index bc79f24..7c4b402 100644
--- a/Scenes/Entities/Enemies/Balloon.gd
+++ b/Scenes/Entities/Enemies/Balloon.gd
@@ -1,9 +1,6 @@
extends CharacterBody2D
-@export var health: int
-
-
func _ready():
add_to_group("enemies")
@@ -22,19 +19,6 @@ func _ready():
$AnimatedSprite2D.play("right")
$AnimatedSprite2D.set_frame_and_progress(frame, progress)
)
-
- get_node("Collision").connect("collided", func(area):
- if area.is_in_group("explosions"):
- health -= 1
- if health <= 0:
- set_physics_process(false)
- remove_child(get_node("Movement"))
-
- $AnimatedSprite2D.play("death")
- await $AnimatedSprite2D.animation_finished
- # todo shrink to 0
- queue_free()
- )
func _physics_process(delta):
diff --git a/Scenes/Entities/Enemies/Balloon.tscn b/Scenes/Entities/Enemies/Balloon.tscn
index 71f6e5d..a9a2cec 100644
--- a/Scenes/Entities/Enemies/Balloon.tscn
+++ b/Scenes/Entities/Enemies/Balloon.tscn
@@ -1,4 +1,4 @@
-[gd_scene load_steps=19 format=3 uid="uid://ccolri3egf8rk"]
+[gd_scene load_steps=20 format=3 uid="uid://ccolri3egf8rk"]
[ext_resource type="Script" path="res://Scenes/Entities/Enemies/Balloon.gd" id="1_8q3w8"]
[ext_resource type="Texture2D" uid="uid://ck1sxw5vqhoa" path="res://Assets/Enemies/Balloon_death_2.png" id="2_c4j5c"]
@@ -16,6 +16,7 @@
[ext_resource type="Texture2D" uid="uid://u56kfb4hq87o" path="res://Assets/Enemies/Balloon_up_2_03.png" id="14_757al"]
[ext_resource type="PackedScene" uid="uid://cq7yj2av01tqd" path="res://Scenes/Entities/Enemies/Components/Movement.tscn" id="15_fwetl"]
[ext_resource type="PackedScene" uid="uid://ce3vv2pod6auc" path="res://Scenes/Entities/Enemies/Components/Collision.tscn" id="16_yau34"]
+[ext_resource type="PackedScene" uid="uid://b3i372vgdbxk" path="res://Scenes/Entities/Enemies/Components/Health.tscn" id="17_d8phm"]
[sub_resource type="SpriteFrames" id="SpriteFrames_nxaqi"]
animations = [{
@@ -42,7 +43,7 @@ animations = [{
}],
"loop": true,
"name": &"down",
-"speed": 2.0
+"speed": 6.0
}, {
"frames": [{
"duration": 1.0,
@@ -59,7 +60,7 @@ animations = [{
}],
"loop": true,
"name": &"left",
-"speed": 2.0
+"speed": 6.0
}, {
"frames": [{
"duration": 1.0,
@@ -76,7 +77,7 @@ animations = [{
}],
"loop": true,
"name": &"right",
-"speed": 2.0
+"speed": 6.0
}, {
"frames": [{
"duration": 1.0,
@@ -93,7 +94,7 @@ animations = [{
}],
"loop": true,
"name": &"up",
-"speed": 2.0
+"speed": 6.0
}]
[sub_resource type="CapsuleShape2D" id="CapsuleShape2D_abul4"]
@@ -102,10 +103,9 @@ height = 15.0
[node name="Balloon" type="CharacterBody2D"]
collision_layer = 16
-collision_mask = 60
+collision_mask = 188
motion_mode = 1
script = ExtResource("1_8q3w8")
-health = 1
[node name="AnimatedSprite2D" type="AnimatedSprite2D" parent="."]
sprite_frames = SubResource("SpriteFrames_nxaqi")
@@ -118,9 +118,15 @@ shape = SubResource("CapsuleShape2D_abul4")
[node name="Movement" parent="." instance=ExtResource("15_fwetl")]
entityPath = NodePath("..")
spritePath = NodePath("../AnimatedSprite2D")
-SPEED = 5
+SPEED = 10
timer_time = 10.0
[node name="Collision" parent="." instance=ExtResource("16_yau34")]
entityPath = NodePath("..")
collision_shape_path = NodePath("../CollisionShape2D")
+component_health_path = NodePath("../Health")
+
+[node name="Health" parent="." instance=ExtResource("17_d8phm")]
+entityPath = NodePath("..")
+spritePath = NodePath("../AnimatedSprite2D")
+health = 1
diff --git a/Scenes/Entities/Enemies/Components/Collision.gd b/Scenes/Entities/Enemies/Components/Collision.gd
index b2e8d9b..2dfba2a 100644
--- a/Scenes/Entities/Enemies/Components/Collision.gd
+++ b/Scenes/Entities/Enemies/Components/Collision.gd
@@ -11,8 +11,19 @@ signal collided
@export_node_path("CollisionShape2D") var collision_shape_path: NodePath
@onready var collision_shape: CollisionShape2D = get_node(collision_shape_path)
+@export_node_path("Component_Health") var component_health_path: NodePath
+var component_health: Component_Health
+
func init():
var collision_area = Utilities.Collision.Area.new(entity, collision_shape)
+ collision_area.set_collision_mask_value(Utilities.Collision.Layer.PLAYER, true)
collision_area.connect("collided", func(area): emit_signal("collided", area))
entity.add_child(collision_area)
+
+ if component_health_path:
+ component_health = get_node(component_health_path)
+ collision_area.connect("collided", func(area):
+ if area.is_in_group("explosions"):
+ component_health.take_damage()
+ )
diff --git a/Scenes/Entities/Enemies/Components/Health.gd b/Scenes/Entities/Enemies/Components/Health.gd
new file mode 100644
index 0000000..f5e231e
--- /dev/null
+++ b/Scenes/Entities/Enemies/Components/Health.gd
@@ -0,0 +1,39 @@
+extends Node
+
+class_name Component_Health
+
+
+@export_node_path("CharacterBody2D") var entityPath: NodePath
+@onready var entity: CharacterBody2D = get_node(entityPath)
+
+@export_node_path("AnimatedSprite2D") var spritePath: NodePath
+@onready var sprite: AnimatedSprite2D = get_node(spritePath)
+
+@export var health: int
+
+
+func take_damage():
+ health -= 1
+
+ if health <= 0:
+ death()
+
+
+func death():
+ entity.set_physics_process(false)
+
+ sprite.play("death")
+ await sprite.animation_finished
+
+ sprite.play("death_post")
+
+ var tween: Tween = get_tree().create_tween()
+ tween.tween_property(
+ entity,
+ "scale",
+ Vector2(0, 0),
+ 1 / sprite.sprite_frames.get_animation_speed("death_post")
+ )
+ tween.tween_callback(func():
+ entity.queue_free()
+ )
diff --git a/Scenes/Entities/Enemies/Components/Health.tscn b/Scenes/Entities/Enemies/Components/Health.tscn
new file mode 100644
index 0000000..6a51704
--- /dev/null
+++ b/Scenes/Entities/Enemies/Components/Health.tscn
@@ -0,0 +1,6 @@
+[gd_scene load_steps=2 format=3 uid="uid://b3i372vgdbxk"]
+
+[ext_resource type="Script" path="res://Scenes/Entities/Enemies/Components/Health.gd" id="1_kjbx0"]
+
+[node name="Health" type="Node"]
+script = ExtResource("1_kjbx0")
diff --git a/Scenes/Entities/Enemies/Components/Movement.gd b/Scenes/Entities/Enemies/Components/Movement.gd
index 6ded026..28b374d 100644
--- a/Scenes/Entities/Enemies/Components/Movement.gd
+++ b/Scenes/Entities/Enemies/Components/Movement.gd
@@ -13,10 +13,15 @@ signal direction_changed
const DIRECTIONS = [Vector2.UP, Vector2.RIGHT, Vector2.DOWN, Vector2.LEFT]
var CURRENT_DIRECTION = Vector2.UP
+var LAST_DIRECTION = Vector2.UP
+var was_colliding = false
@export var timer_time: float = 3.0
@onready var MovementTimer: Timer = Timer.new()
+@export var follows: bool = false
+@export_range(1, 100, 1) var follow_chance: int = 100
+
func _ready():
MovementTimer.wait_time = timer_time
@@ -28,35 +33,67 @@ func _ready():
func physics_process(delta):
if CURRENT_DIRECTION == Vector2.UP:
entity.velocity.y -= SPEED
- sprite.play("up")
+ if sprite.sprite_frames.has_animation("up"):
+ sprite.play("up")
elif CURRENT_DIRECTION == Vector2.DOWN:
entity.velocity.y += SPEED
- sprite.play("down")
+ if sprite.sprite_frames.has_animation("down"):
+ sprite.play("down")
elif CURRENT_DIRECTION == Vector2.LEFT:
entity.velocity.x -= SPEED
- sprite.play("left")
+ if sprite.sprite_frames.has_animation("leftup"):
+ sprite.play("left")
elif CURRENT_DIRECTION == Vector2.RIGHT:
entity.velocity.x += SPEED
- sprite.play("right")
+ if sprite.sprite_frames.has_animation("right"):
+ sprite.play("right")
+
+ if sprite.sprite_frames.has_animation("default"):
+ sprite.play("default")
var collision = entity.move_and_collide(entity.velocity * delta)
entity.velocity = entity.velocity.lerp(Vector2(0, 0), 1) # speed too low => no collision
if collision:
+ was_colliding = true
if MovementTimer.time_left > 0:
_on_movement_timer_timeout()
+ else:
+ was_colliding = false
return collision
func _on_movement_timer_timeout():
- var directions = DIRECTIONS.duplicate()
-
- directions.remove_at(directions.find(CURRENT_DIRECTION))
- directions.shuffle()
-
- CURRENT_DIRECTION = directions[0]
+ var randomize_direction = false
+
+ if follows and randi_range(0, 100) <= follow_chance:
+ var player_direction = entity.position.direction_to(Global.player.position)
+ if abs(player_direction.x) >= abs(player_direction.y):
+ if player_direction.x >= 0:
+ CURRENT_DIRECTION = Vector2.RIGHT
+ elif player_direction.x < 0:
+ CURRENT_DIRECTION = Vector2.LEFT
+ elif abs(player_direction.y) > abs(player_direction.x):
+ if player_direction.y >= 0:
+ CURRENT_DIRECTION = Vector2.DOWN
+ elif player_direction.y < 0:
+ CURRENT_DIRECTION = Vector2.UP
+
+ if was_colliding and LAST_DIRECTION == CURRENT_DIRECTION:
+ randomize_direction = true
+ else:
+ randomize_direction = true
+
+ if randomize_direction:
+ var directions = DIRECTIONS.duplicate()
+
+ directions.remove_at(directions.find(CURRENT_DIRECTION))
+ directions.shuffle()
+
+ CURRENT_DIRECTION = directions[0]
emit_signal("direction_changed", CURRENT_DIRECTION)
+ LAST_DIRECTION = CURRENT_DIRECTION
MovementTimer.start()
diff --git a/Scenes/Entities/Enemies/Slime.gd b/Scenes/Entities/Enemies/Slime.gd
new file mode 100644
index 0000000..427b18f
--- /dev/null
+++ b/Scenes/Entities/Enemies/Slime.gd
@@ -0,0 +1,11 @@
+extends CharacterBody2D
+
+
+func _ready():
+ add_to_group("enemies")
+
+ get_node("Collision").init()
+
+
+func _physics_process(delta):
+ get_node("Movement").physics_process(delta)
diff --git a/Scenes/Entities/Enemies/Slime.tscn b/Scenes/Entities/Enemies/Slime.tscn
new file mode 100644
index 0000000..f30d161
--- /dev/null
+++ b/Scenes/Entities/Enemies/Slime.tscn
@@ -0,0 +1,68 @@
+[gd_scene load_steps=11 format=3 uid="uid://d3evry1ketf0s"]
+
+[ext_resource type="Script" path="res://Scenes/Entities/Enemies/Slime.gd" id="1_2xftl"]
+[ext_resource type="Texture2D" uid="uid://ca7oars0vec8k" path="res://Assets/Enemies/Slime_death.png" id="2_mqou3"]
+[ext_resource type="Texture2D" uid="uid://b88dvu2ridy4t" path="res://Assets/Enemies/Slime_01.png" id="3_20mej"]
+[ext_resource type="Texture2D" uid="uid://bndhg7wom64mq" path="res://Assets/Enemies/Slime_02.png" id="4_r6mjl"]
+[ext_resource type="Texture2D" uid="uid://dh7vaujrw6i26" path="res://Assets/Enemies/Slime_03.png" id="5_mm7vy"]
+[ext_resource type="PackedScene" uid="uid://cq7yj2av01tqd" path="res://Scenes/Entities/Enemies/Components/Movement.tscn" id="6_u48ct"]
+[ext_resource type="PackedScene" uid="uid://ce3vv2pod6auc" path="res://Scenes/Entities/Enemies/Components/Collision.tscn" id="7_kjjor"]
+[ext_resource type="PackedScene" uid="uid://b3i372vgdbxk" path="res://Scenes/Entities/Enemies/Components/Health.tscn" id="8_klsy3"]
+
+[sub_resource type="CircleShape2D" id="CircleShape2D_f54tg"]
+radius = 7.0
+
+[sub_resource type="SpriteFrames" id="SpriteFrames_4e1a7"]
+animations = [{
+"frames": [{
+"duration": 1.0,
+"texture": ExtResource("2_mqou3")
+}],
+"loop": false,
+"name": &"death",
+"speed": 2.0
+}, {
+"frames": [{
+"duration": 1.0,
+"texture": ExtResource("3_20mej")
+}, {
+"duration": 1.0,
+"texture": ExtResource("4_r6mjl")
+}, {
+"duration": 1.0,
+"texture": ExtResource("3_20mej")
+}, {
+"duration": 1.0,
+"texture": ExtResource("5_mm7vy")
+}],
+"loop": true,
+"name": &"default",
+"speed": 8.0
+}]
+
+[node name="Slime" type="CharacterBody2D"]
+collision_layer = 16
+collision_mask = 188
+script = ExtResource("1_2xftl")
+
+[node name="CollisionShape2D" type="CollisionShape2D" parent="."]
+shape = SubResource("CircleShape2D_f54tg")
+
+[node name="AnimatedSprite2D" type="AnimatedSprite2D" parent="."]
+sprite_frames = SubResource("SpriteFrames_4e1a7")
+
+[node name="Movement" parent="." instance=ExtResource("6_u48ct")]
+entityPath = NodePath("..")
+spritePath = NodePath("../AnimatedSprite2D")
+SPEED = 12
+timer_time = 5.0
+
+[node name="Collision" parent="." instance=ExtResource("7_kjjor")]
+entityPath = NodePath("..")
+collision_shape_path = NodePath("../CollisionShape2D")
+component_health_path = NodePath("../Health")
+
+[node name="Health" parent="." instance=ExtResource("8_klsy3")]
+entityPath = NodePath("..")
+spritePath = NodePath("../AnimatedSprite2D")
+health = 1
diff --git a/Scenes/Entities/Enemies/Tree.gd b/Scenes/Entities/Enemies/Tree.gd
new file mode 100644
index 0000000..7c87a18
--- /dev/null
+++ b/Scenes/Entities/Enemies/Tree.gd
@@ -0,0 +1,22 @@
+extends CharacterBody2D
+
+
+func _ready():
+ add_to_group("enemies")
+
+ get_node("Collision").init()
+
+ set_physics_process(false)
+ $AnimatedSprite2D.play("spawn")
+ $AnimatedSprite2D.stop()
+ $AnimatedSprite2D.set_frame_and_progress(0, 0)
+
+
+func _physics_process(delta):
+ get_node("Movement").physics_process(delta)
+
+
+func _on_detection_body_entered(body):
+ $AnimatedSprite2D.play("spawn")
+ await $AnimatedSprite2D.animation_finished
+ set_physics_process(true)
diff --git a/Scenes/Entities/Enemies/Tree.tscn b/Scenes/Entities/Enemies/Tree.tscn
new file mode 100644
index 0000000..aedc79f
--- /dev/null
+++ b/Scenes/Entities/Enemies/Tree.tscn
@@ -0,0 +1,175 @@
+[gd_scene load_steps=28 format=3 uid="uid://bjgcrqdntj5hl"]
+
+[ext_resource type="Script" path="res://Scenes/Entities/Enemies/Tree.gd" id="1_ktvfx"]
+[ext_resource type="Texture2D" uid="uid://bv1rs3ndtyqfx" path="res://Assets/Enemies/Tree_death.png" id="2_0yhl7"]
+[ext_resource type="Texture2D" uid="uid://cpl4n4jmgiwrv" path="res://Assets/Enemies/Enemy_death_01_01.png" id="3_2k0yc"]
+[ext_resource type="Texture2D" uid="uid://q7a7i15t8wpt" path="res://Assets/Enemies/Tree_spawn_10.png" id="3_7e4uh"]
+[ext_resource type="Texture2D" uid="uid://61nopmi2r6o2" path="res://Assets/Enemies/Tree_02.png" id="4_7rbqf"]
+[ext_resource type="Texture2D" uid="uid://d2gk5amafhctu" path="res://Assets/Enemies/Enemy_death_01_02.png" id="4_15pyx"]
+[ext_resource type="Texture2D" uid="uid://dqwxq3g3aph4i" path="res://Assets/Enemies/Enemy_death_01_03.png" id="5_7xj1s"]
+[ext_resource type="Texture2D" uid="uid://cjapfj57h55t3" path="res://Assets/Enemies/Tree_01.png" id="5_r5my6"]
+[ext_resource type="Texture2D" uid="uid://uoj5222vlq8q" path="res://Assets/Enemies/Enemy_death_01_04.png" id="6_5dleo"]
+[ext_resource type="Texture2D" uid="uid://divyusx4566qu" path="res://Assets/Enemies/Tree_spawn_01.png" id="6_uumup"]
+[ext_resource type="Texture2D" uid="uid://cxx2vv1ohiw07" path="res://Assets/Enemies/Enemy_death_01_05.png" id="7_n5hht"]
+[ext_resource type="Texture2D" uid="uid://bydf14nlpwcdx" path="res://Assets/Enemies/Tree_spawn_02.png" id="7_ogluj"]
+[ext_resource type="Texture2D" uid="uid://rx27eawdqihg" path="res://Assets/Enemies/Tree_spawn_03.png" id="8_lr37s"]
+[ext_resource type="Texture2D" uid="uid://b6raflxfxgafu" path="res://Assets/Enemies/Tree_spawn_04.png" id="9_4yykj"]
+[ext_resource type="Texture2D" uid="uid://cpyqewp3he31s" path="res://Assets/Enemies/Tree_spawn_05.png" id="10_1nh66"]
+[ext_resource type="Texture2D" uid="uid://cus616lvay47x" path="res://Assets/Enemies/Tree_spawn_06.png" id="11_qdau7"]
+[ext_resource type="Texture2D" uid="uid://lxqkmqie5vx1" path="res://Assets/Enemies/Tree_spawn_07.png" id="12_wsl7r"]
+[ext_resource type="Texture2D" uid="uid://psbdavhnvvn4" path="res://Assets/Enemies/Tree_spawn_08.png" id="13_2wcu3"]
+[ext_resource type="Texture2D" uid="uid://dfbuswdlfqylq" path="res://Assets/Enemies/Tree_spawn_09.png" id="14_adw3w"]
+[ext_resource type="Texture2D" uid="uid://brqywegqyotsh" path="res://Assets/Enemies/Tree_spawn_11.png" id="15_tpc2s"]
+[ext_resource type="Texture2D" uid="uid://bwfe51nka048i" path="res://Assets/Enemies/Tree_spawn_12.png" id="16_vf63h"]
+[ext_resource type="PackedScene" uid="uid://cq7yj2av01tqd" path="res://Scenes/Entities/Enemies/Components/Movement.tscn" id="17_wlky1"]
+[ext_resource type="PackedScene" uid="uid://ce3vv2pod6auc" path="res://Scenes/Entities/Enemies/Components/Collision.tscn" id="18_kpty6"]
+[ext_resource type="PackedScene" uid="uid://b3i372vgdbxk" path="res://Scenes/Entities/Enemies/Components/Health.tscn" id="19_u7yi8"]
+
+[sub_resource type="SpriteFrames" id="SpriteFrames_c5ryj"]
+animations = [{
+"frames": [{
+"duration": 1.0,
+"texture": ExtResource("2_0yhl7")
+}],
+"loop": false,
+"name": &"death",
+"speed": 1.0
+}, {
+"frames": [{
+"duration": 1.0,
+"texture": ExtResource("3_2k0yc")
+}, {
+"duration": 1.0,
+"texture": ExtResource("4_15pyx")
+}, {
+"duration": 1.0,
+"texture": ExtResource("5_7xj1s")
+}, {
+"duration": 1.0,
+"texture": ExtResource("6_5dleo")
+}, {
+"duration": 1.0,
+"texture": ExtResource("7_n5hht")
+}],
+"loop": true,
+"name": &"death_post",
+"speed": 2.0
+}, {
+"frames": [{
+"duration": 1.0,
+"texture": ExtResource("3_7e4uh")
+}, {
+"duration": 1.0,
+"texture": ExtResource("4_7rbqf")
+}, {
+"duration": 1.0,
+"texture": ExtResource("5_r5my6")
+}, {
+"duration": 1.0,
+"texture": ExtResource("4_7rbqf")
+}],
+"loop": true,
+"name": &"default",
+"speed": 6.0
+}, {
+"frames": [{
+"duration": 1.0,
+"texture": ExtResource("6_uumup")
+}, {
+"duration": 1.0,
+"texture": ExtResource("7_ogluj")
+}, {
+"duration": 1.0,
+"texture": ExtResource("6_uumup")
+}, {
+"duration": 1.0,
+"texture": ExtResource("7_ogluj")
+}, {
+"duration": 1.0,
+"texture": ExtResource("6_uumup")
+}, {
+"duration": 1.0,
+"texture": ExtResource("7_ogluj")
+}, {
+"duration": 1.0,
+"texture": ExtResource("8_lr37s")
+}, {
+"duration": 1.0,
+"texture": ExtResource("9_4yykj")
+}, {
+"duration": 1.0,
+"texture": ExtResource("10_1nh66")
+}, {
+"duration": 1.0,
+"texture": ExtResource("11_qdau7")
+}, {
+"duration": 1.0,
+"texture": ExtResource("12_wsl7r")
+}, {
+"duration": 1.0,
+"texture": ExtResource("13_2wcu3")
+}, {
+"duration": 1.0,
+"texture": ExtResource("14_adw3w")
+}, {
+"duration": 1.0,
+"texture": ExtResource("3_7e4uh")
+}, {
+"duration": 1.0,
+"texture": ExtResource("15_tpc2s")
+}, {
+"duration": 1.0,
+"texture": ExtResource("16_vf63h")
+}],
+"loop": false,
+"name": &"spawn",
+"speed": 6.0
+}]
+
+[sub_resource type="CapsuleShape2D" id="CapsuleShape2D_u8qfj"]
+height = 22.0
+
+[sub_resource type="CircleShape2D" id="CircleShape2D_ymwt3"]
+radius = 48.0
+
+[node name="Tree" type="CharacterBody2D"]
+collision_layer = 16
+collision_mask = 188
+script = ExtResource("1_ktvfx")
+
+[node name="AnimatedSprite2D" type="AnimatedSprite2D" parent="."]
+position = Vector2(0, -8)
+sprite_frames = SubResource("SpriteFrames_c5ryj")
+animation = &"spawn"
+
+[node name="CollisionShape2D" type="CollisionShape2D" parent="."]
+position = Vector2(0, -8)
+shape = SubResource("CapsuleShape2D_u8qfj")
+
+[node name="Movement" parent="." instance=ExtResource("17_wlky1")]
+entityPath = NodePath("..")
+spritePath = NodePath("../AnimatedSprite2D")
+SPEED = 24
+timer_time = 2.0
+follows = true
+follow_chance = 50
+
+[node name="Collision" parent="." instance=ExtResource("18_kpty6")]
+entityPath = NodePath("..")
+collision_shape_path = NodePath("../CollisionShape2D")
+component_health_path = NodePath("../Health")
+
+[node name="Health" parent="." instance=ExtResource("19_u7yi8")]
+entityPath = NodePath("..")
+spritePath = NodePath("../AnimatedSprite2D")
+health = 1
+
+[node name="Detection" type="Area2D" parent="."]
+collision_layer = 64
+collision_mask = 2
+
+[node name="CollisionShape2D" type="CollisionShape2D" parent="Detection"]
+position = Vector2(0, -8)
+shape = SubResource("CircleShape2D_ymwt3")
+
+[connection signal="body_entered" from="Detection" to="." method="_on_detection_body_entered"]