Add basic enemy behavior and spawning system

The changes introduce enemy mechanics and management - including
spawning, movement patterns, shooting timers, and death handling.
This commit is contained in:
Henry 2025-10-13 18:55:09 +01:00
parent 85155b1c7d
commit 996a0bb8f7
8 changed files with 300 additions and 7 deletions

41
scenes/enemy.gd Normal file
View file

@ -0,0 +1,41 @@
extends Area2D
signal died
var start_pos = Vector2.ZERO
var speed = 0
@onready var screensize = get_viewport_rect().size
func start(pos):
speed = 0
position = Vector2(pos.x, -pos.y)
start_pos = pos
await get_tree().create_timer(randf_range(0.25, 0.55)).timeout
var tween = create_tween().set_trans(Tween.TRANS_BACK)
tween.tween_property(self, "position:y", start_pos.y, 1.4)
await tween.finished
$MoveTimer.wait_time = randf_range(5, 20)
$MoveTimer.start()
$ShootTimer.wait_time = randf_range(4, 20)
$ShootTimer.start()
func _on_timer_timeout():
speed = randf_range(75, 100)
func _on_shoot_timer_timeout():
$ShootTimer.wait_time = randf_range(4, 20)
$ShootTimer.start()
func _process(delta):
position.y += speed * delta
if position.y > screensize.y + 32:
start(start_pos)
func explode():
speed = 0
$AnimationPlayer.play("explode")
set_deferred("monitoring", false)
died.emit(5)
await $AnimationPlayer.animation_finished
queue_free()

1
scenes/enemy.gd.uid Normal file
View file

@ -0,0 +1 @@
uid://bgdjbphv28w25

164
scenes/enemy.tscn Normal file
View file

@ -0,0 +1,164 @@
[gd_scene load_steps=9 format=3 uid="uid://c4vq2ytntfvoj"]
[ext_resource type="Script" uid="uid://bgdjbphv28w25" path="res://scenes/enemy.gd" id="1_55jtl"]
[ext_resource type="Texture2D" uid="uid://deyu1prtitqcp" path="res://resources/Mini Pixel Pack 3/Enemies/Bon_Bon (16 x 16).png" id="2_mpr68"]
[ext_resource type="Texture2D" uid="uid://h04wm5a27u0" path="res://resources/Mini Pixel Pack 3/Effects/Explosion (16 x 16).png" id="3_4ra3w"]
[sub_resource type="RectangleShape2D" id="RectangleShape2D_ft8do"]
size = Vector2(14, 12)
[sub_resource type="Animation" id="Animation_1vja8"]
length = 0.001
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("Sprite2D:texture")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [ExtResource("2_mpr68")]
}
tracks/1/type = "value"
tracks/1/imported = false
tracks/1/enabled = true
tracks/1/path = NodePath("Sprite2D:hframes")
tracks/1/interp = 1
tracks/1/loop_wrap = true
tracks/1/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [4]
}
tracks/2/type = "value"
tracks/2/imported = false
tracks/2/enabled = true
tracks/2/path = NodePath("Sprite2D:frame")
tracks/2/interp = 1
tracks/2/loop_wrap = true
tracks/2/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [2]
}
[sub_resource type="Animation" id="Animation_5wwv6"]
resource_name = "bounce"
loop_mode = 1
step = 0.05
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("Sprite2D:texture")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [ExtResource("2_mpr68")]
}
tracks/1/type = "value"
tracks/1/imported = false
tracks/1/enabled = true
tracks/1/path = NodePath("Sprite2D:hframes")
tracks/1/interp = 1
tracks/1/loop_wrap = true
tracks/1/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [4]
}
tracks/2/type = "value"
tracks/2/imported = false
tracks/2/enabled = true
tracks/2/path = NodePath("Sprite2D:frame")
tracks/2/interp = 1
tracks/2/loop_wrap = true
tracks/2/keys = {
"times": PackedFloat32Array(0.1, 0.2, 0.3, 0.4, 0.45),
"transitions": PackedFloat32Array(1, 1, 1, 1, 1),
"update": 1,
"values": [2, 1, 0, 3, 0]
}
[sub_resource type="Animation" id="Animation_iwav8"]
resource_name = "explode"
length = 0.4
step = 0.05
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("Sprite2D:texture")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [ExtResource("3_4ra3w")]
}
tracks/1/type = "value"
tracks/1/imported = false
tracks/1/enabled = true
tracks/1/path = NodePath("Sprite2D:frame")
tracks/1/interp = 1
tracks/1/loop_wrap = true
tracks/1/keys = {
"times": PackedFloat32Array(0, 0.042729422, 0.1, 0.15, 0.4),
"transitions": PackedFloat32Array(1, 1, 1, 1, 1),
"update": 1,
"values": [0, 2, 3, 4, 5]
}
tracks/2/type = "value"
tracks/2/imported = false
tracks/2/enabled = true
tracks/2/path = NodePath("Sprite2D:hframes")
tracks/2/interp = 1
tracks/2/loop_wrap = true
tracks/2/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [6]
}
[sub_resource type="AnimationLibrary" id="AnimationLibrary_1i2q2"]
_data = {
&"RESET": SubResource("Animation_1vja8"),
&"bounce": SubResource("Animation_5wwv6"),
&"explode": SubResource("Animation_iwav8")
}
[node name="Enemy" type="Area2D" groups=["enemies"]]
script = ExtResource("1_55jtl")
[node name="Sprite2D" type="Sprite2D" parent="."]
position = Vector2(0, -3)
texture = ExtResource("2_mpr68")
hframes = 4
frame = 2
[node name="CollisionShape2D" type="CollisionShape2D" parent="."]
position = Vector2(0, -3)
shape = SubResource("RectangleShape2D_ft8do")
[node name="AnimationPlayer" type="AnimationPlayer" parent="."]
libraries = {
&"": SubResource("AnimationLibrary_1i2q2")
}
autoplay = "bounce"
[node name="MoveTimer" type="Timer" parent="."]
one_shot = true
[node name="ShootTimer" type="Timer" parent="."]
one_shot = true
[connection signal="timeout" from="MoveTimer" to="." method="_on_move_timer_timeout"]
[connection signal="timeout" from="ShootTimer" to="." method="_on_shoot_timer_timeout"]

10
scenes/game.tscn Normal file
View file

@ -0,0 +1,10 @@
[gd_scene load_steps=3 format=3 uid="uid://oq85kpt7a853"]
[ext_resource type="PackedScene" uid="uid://ssdtocwmj0wj" path="res://scenes/start.tscn" id="1_yqjtg"]
[ext_resource type="PackedScene" uid="uid://brutkgnx73onj" path="res://scenes/gameplay.tscn" id="2_lnu2h"]
[node name="Game" type="Node2D"]
[node name="Start" parent="." instance=ExtResource("1_yqjtg")]
[node name="Gameplay" parent="." instance=ExtResource("2_lnu2h")]

20
scenes/main.gd Normal file
View file

@ -0,0 +1,20 @@
extends Node2D
var enemy = preload("res://scenes/enemy.tscn")
var score = 0
func _ready():
spawn_enemies()
func spawn_enemies():
for x in range(9):
for y in range(3):
var e = enemy.instantiate()
var pos = Vector2(x * (16 + 8) + 24, 16 * 4 + y * 16)
add_child(e)
e.start(pos)
e.died.connect(_on_enemy_died)
func _on_enemy_died(value):
score += value

1
scenes/main.gd.uid Normal file
View file

@ -0,0 +1 @@
uid://b2tub370i3s3v

View file

@ -1,10 +1,64 @@
[gd_scene load_steps=3 format=3 uid="uid://oq85kpt7a853"]
[gd_scene load_steps=8 format=3 uid="uid://ce5rw02b3373d"]
[ext_resource type="PackedScene" uid="uid://ssdtocwmj0wj" path="res://scenes/start.tscn" id="1_0wfyh"]
[ext_resource type="PackedScene" uid="uid://brutkgnx73onj" path="res://scenes/gameplay.tscn" id="2_sugp2"]
[ext_resource type="Script" uid="uid://b2tub370i3s3v" path="res://scenes/main.gd" id="1_jyhfs"]
[ext_resource type="Texture2D" uid="uid://jj8b7vqj3ihx" path="res://resources/Mini Pixel Pack 3/Space_BG (2 frames) (64 x 64).png" id="2_tbgi4"]
[ext_resource type="PackedScene" uid="uid://bkuucjejc7p2v" path="res://scenes/player.tscn" id="3_tefeu"]
[ext_resource type="PackedScene" uid="uid://c4vq2ytntfvoj" path="res://scenes/enemy.tscn" id="4_o6xl0"]
[sub_resource type="Animation" id="Animation_vcsgt"]
length = 0.001
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("Background:region_rect")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 0,
"values": [Rect2(0, 0, 240, 320)]
}
[sub_resource type="Animation" id="Animation_rarhs"]
resource_name = "scroll"
length = 2.0
loop_mode = 1
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("Background:region_rect")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0, 2),
"transitions": PackedFloat32Array(1, 1),
"update": 0,
"values": [Rect2(0, 0, 240, 320), Rect2(0, -64, 240, 320)]
}
[sub_resource type="AnimationLibrary" id="AnimationLibrary_c01mt"]
_data = {
&"RESET": SubResource("Animation_vcsgt"),
&"scroll": SubResource("Animation_rarhs")
}
[node name="Main" type="Node2D"]
script = ExtResource("1_jyhfs")
[node name="Start" parent="." instance=ExtResource("1_0wfyh")]
[node name="Background" type="Sprite2D" parent="."]
texture_repeat = 2
texture = ExtResource("2_tbgi4")
centered = false
region_enabled = true
region_rect = Rect2(0, 0, 240, 320)
[node name="Gameplay" parent="." instance=ExtResource("2_sugp2")]
[node name="Player" parent="." instance=ExtResource("3_tefeu")]
[node name="AnimationPlayer" type="AnimationPlayer" parent="."]
libraries = {
&"": SubResource("AnimationLibrary_c01mt")
}
autoplay = "scroll"
[node name="Enemy" parent="." instance=ExtResource("4_o6xl0")]

View file

@ -1,6 +1,7 @@
[gd_scene load_steps=14 format=3 uid="uid://bkuucjejc7p2v"]
[gd_scene load_steps=15 format=3 uid="uid://bkuucjejc7p2v"]
[ext_resource type="Script" uid="uid://c7fe5pl54gkem" path="res://scenes/player.gd" id="1_qlg0r"]
[ext_resource type="PackedScene" uid="uid://bus77xvomweiu" path="res://scenes/bullet.tscn" id="2_fjrip"]
[ext_resource type="Texture2D" uid="uid://di2xhcwcdbhxg" path="res://resources/Mini Pixel Pack 3/Player ship/Player_ship (16 x 16).png" id="2_tuyoq"]
[ext_resource type="Texture2D" uid="uid://ces8fm7lxh574" path="res://resources/Mini Pixel Pack 3/Player ship/Boosters (16 x 16).png" id="3_fjrip"]
[ext_resource type="Texture2D" uid="uid://bjdhq42ummgky" path="res://resources/Mini Pixel Pack 3/Player ship/Boosters_left (16 x 16).png" id="4_smehm"]
@ -71,6 +72,7 @@ size = Vector2(14, 14)
[node name="Player" type="Area2D"]
script = ExtResource("1_qlg0r")
bullet_scene = ExtResource("2_fjrip")
[node name="Ship" type="Sprite2D" parent="."]
texture = ExtResource("2_tuyoq")
@ -87,7 +89,7 @@ autoplay = "forward"
shape = SubResource("RectangleShape2D_w3w6i")
[node name="GunCooldown" type="Timer" parent="."]
wait_time = 0.001
wait_time = 0.24
one_shot = true
[connection signal="timeout" from="GunCooldown" to="." method="_on_gun_cooldown_timeout"]