Compare commits

...

14 Commits

Author SHA1 Message Date
Jaro Winkelhausen 9a82e74e41 add a knive perk where the witch initally throws a knive every 2 seconds with subsequent upgrades until the cooldown is 1s between throws (#10)
Reviewed-on: #10
Co-authored-by: 3002102 <3002102@stud.hs-mannheim.de>
Co-committed-by: 3002102 <3002102@stud.hs-mannheim.de>
2026-04-15 19:09:21 +02:00
Jaro Winkelhausen 01648c5939 add feature to wave logic for boss wave (#9)
Reviewed-on: #9
Co-authored-by: 3002102 <3002102@stud.hs-mannheim.de>
Co-committed-by: 3002102 <3002102@stud.hs-mannheim.de>
2026-04-15 18:19:55 +02:00
Jaro Winkelhausen fc40a5c368 add timer to the ui (#8)
Reviewed-on: #8
Co-authored-by: 3002102 <3002102@stud.hs-mannheim.de>
Co-committed-by: 3002102 <3002102@stud.hs-mannheim.de>
2026-04-15 18:14:52 +02:00
Artur e46b196f71 translated perks desc and name 2026-04-15 18:03:56 +02:00
Artur 671c046c3c Merge branch 'main' of https://gitty.informatik.hs-mannheim.de/3002102/gae_wild_jam 2026-04-15 18:00:03 +02:00
Artur f5bbfd839a fxied uid hell 2026-04-15 18:00:02 +02:00
Jaro Winkelhausen c6277ccf22 fixed issue where the closer the enemies get to the with the slower they become (#7)
Reviewed-on: #7
Co-authored-by: 3002102 <3002102@stud.hs-mannheim.de>
Co-committed-by: 3002102 <3002102@stud.hs-mannheim.de>
2026-04-15 17:57:41 +02:00
Artur 5ee8c97455 Merge branch 'main' of https://gitty.informatik.hs-mannheim.de/3002102/gae_wild_jam 2026-04-15 17:49:11 +02:00
Artur b9f024685b Merge branch 'better-perk-display' 2026-04-15 17:48:25 +02:00
Jaro Winkelhausen 6a2b122343 fixed error in fireball due to the boom effect from upgrade (#6)
Reviewed-on: #6
Co-authored-by: 3002102 <3002102@stud.hs-mannheim.de>
Co-committed-by: 3002102 <3002102@stud.hs-mannheim.de>
2026-04-15 17:47:27 +02:00
Jaro Winkelhausen 4a4a664fee add a new wave spawning logic defined by a spawn_stages.json in the data folder (#5)
Reviewed-on: #5
Co-authored-by: 3002102 <3002102@stud.hs-mannheim.de>
Co-committed-by: 3002102 <3002102@stud.hs-mannheim.de>
2026-04-15 17:34:40 +02:00
Jaro Winkelhausen 8b76140c2a add new fire slime with three hp (#3)
Reviewed-on: #3
Co-authored-by: 3002102 <3002102@stud.hs-mannheim.de>
Co-committed-by: 3002102 <3002102@stud.hs-mannheim.de>
2026-04-15 17:05:54 +02:00
Meik Schürmann fa50773a0e Merge pull request 'implemented pause menu, fixed bug of music not looping' (#2) from menuing_and_audio into main
Reviewed-on: #2
2026-04-15 10:49:07 +02:00
Meik Schürmann fa2e3cfc9a implemented pause menu, fixed bug of music not looping 2026-04-15 10:46:27 +02:00
27 changed files with 1309 additions and 71 deletions

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 263 B

View File

@ -0,0 +1,40 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://pot4k8a6lxd0"
path="res://.godot/imported/knvie.png-6e2c57d6850f97653fad709f2c5186b5.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://assets/weapons/knvie.png"
dest_files=["res://.godot/imported/knvie.png-6e2c57d6850f97653fad709f2c5186b5.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
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/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
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

View File

@ -0,0 +1,26 @@
[
{
"time_start": 0,
"time_end": 60,
"entries": [
{ "enemy": "res://scenes/slime.tscn", "count_at_start": 0, "count_at_end": 15, "min_interval": 0.5 }
]
},
{
"time_start": 60,
"time_end": 180,
"entries": [
{ "enemy": "res://scenes/slime.tscn", "count_at_start": 15, "count_at_end": 40, "min_interval": 0.3 },
{ "enemy": "res://scenes/blue_slime.tscn", "count_at_start": 0, "count_at_end": 10, "min_interval": 0.8 }
]
},
{
"time_start": 180,
"time_end": -1,
"entries": [
{ "enemy": "res://scenes/slime.tscn", "count_at_start": 40, "count_at_end": 100, "min_interval": 0.2 },
{ "enemy": "res://scenes/blue_slime.tscn", "count_at_start": 10, "count_at_end": 60, "min_interval": 0.5 },
{ "enemy": "res://scenes/fire_slime.tscn", "count_at_start": 0, "count_at_end": 40, "min_interval": 0.6 }
]
}
]

View File

@ -0,0 +1,752 @@
[gd_scene format=3 uid="uid://cpe6aiuqiox0u"]
[ext_resource type="Script" uid="uid://dklt42vjjcks7" path="res://scripts/fire_slime.gd" id="1_88j2t"]
[ext_resource type="Texture2D" uid="uid://b1tyfy8ooudkc" path="res://assets/Slime3/With_shadow/Slime3_Death_with_shadow.png" id="2_ahfdi"]
[ext_resource type="Texture2D" uid="uid://bbm1sv6hmc2j" path="res://assets/Slime3/With_shadow/Slime3_Hurt_with_shadow.png" id="3_kq38e"]
[ext_resource type="Texture2D" uid="uid://bt07131sttb6e" path="res://assets/Slime3/With_shadow/Slime3_Walk_with_shadow.png" id="4_ret1g"]
[sub_resource type="AtlasTexture" id="AtlasTexture_u74be"]
atlas = ExtResource("2_ahfdi")
region = Rect2(0, 0, 64, 64)
[sub_resource type="AtlasTexture" id="AtlasTexture_hky14"]
atlas = ExtResource("2_ahfdi")
region = Rect2(64, 0, 64, 64)
[sub_resource type="AtlasTexture" id="AtlasTexture_1hmrm"]
atlas = ExtResource("2_ahfdi")
region = Rect2(128, 0, 64, 64)
[sub_resource type="AtlasTexture" id="AtlasTexture_icdnf"]
atlas = ExtResource("2_ahfdi")
region = Rect2(192, 0, 64, 64)
[sub_resource type="AtlasTexture" id="AtlasTexture_jpau6"]
atlas = ExtResource("2_ahfdi")
region = Rect2(256, 0, 64, 64)
[sub_resource type="AtlasTexture" id="AtlasTexture_pla0y"]
atlas = ExtResource("2_ahfdi")
region = Rect2(320, 0, 64, 64)
[sub_resource type="AtlasTexture" id="AtlasTexture_5ug5i"]
atlas = ExtResource("2_ahfdi")
region = Rect2(384, 0, 64, 64)
[sub_resource type="AtlasTexture" id="AtlasTexture_p0q1e"]
atlas = ExtResource("2_ahfdi")
region = Rect2(448, 0, 64, 64)
[sub_resource type="AtlasTexture" id="AtlasTexture_8gdmr"]
atlas = ExtResource("2_ahfdi")
region = Rect2(512, 0, 64, 64)
[sub_resource type="AtlasTexture" id="AtlasTexture_4gxlk"]
atlas = ExtResource("2_ahfdi")
region = Rect2(576, 0, 64, 64)
[sub_resource type="AtlasTexture" id="AtlasTexture_w642b"]
atlas = ExtResource("2_ahfdi")
region = Rect2(256, 0, 64, 64)
[sub_resource type="AtlasTexture" id="AtlasTexture_6tf61"]
atlas = ExtResource("2_ahfdi")
region = Rect2(0, 128, 64, 64)
[sub_resource type="AtlasTexture" id="AtlasTexture_354yo"]
atlas = ExtResource("2_ahfdi")
region = Rect2(64, 128, 64, 64)
[sub_resource type="AtlasTexture" id="AtlasTexture_wrhhh"]
atlas = ExtResource("2_ahfdi")
region = Rect2(128, 128, 64, 64)
[sub_resource type="AtlasTexture" id="AtlasTexture_5l6b7"]
atlas = ExtResource("2_ahfdi")
region = Rect2(192, 128, 64, 64)
[sub_resource type="AtlasTexture" id="AtlasTexture_ml8lr"]
atlas = ExtResource("2_ahfdi")
region = Rect2(256, 128, 64, 64)
[sub_resource type="AtlasTexture" id="AtlasTexture_flrsr"]
atlas = ExtResource("2_ahfdi")
region = Rect2(320, 128, 64, 64)
[sub_resource type="AtlasTexture" id="AtlasTexture_qr4cj"]
atlas = ExtResource("2_ahfdi")
region = Rect2(384, 128, 64, 64)
[sub_resource type="AtlasTexture" id="AtlasTexture_o5jey"]
atlas = ExtResource("2_ahfdi")
region = Rect2(448, 128, 64, 64)
[sub_resource type="AtlasTexture" id="AtlasTexture_1fjmf"]
atlas = ExtResource("2_ahfdi")
region = Rect2(512, 128, 64, 64)
[sub_resource type="AtlasTexture" id="AtlasTexture_3dxre"]
atlas = ExtResource("2_ahfdi")
region = Rect2(576, 128, 64, 64)
[sub_resource type="AtlasTexture" id="AtlasTexture_6mupu"]
atlas = ExtResource("2_ahfdi")
region = Rect2(0, 192, 64, 64)
[sub_resource type="AtlasTexture" id="AtlasTexture_cpqhb"]
atlas = ExtResource("2_ahfdi")
region = Rect2(64, 192, 64, 64)
[sub_resource type="AtlasTexture" id="AtlasTexture_vpjp1"]
atlas = ExtResource("2_ahfdi")
region = Rect2(128, 192, 64, 64)
[sub_resource type="AtlasTexture" id="AtlasTexture_pyvbc"]
atlas = ExtResource("2_ahfdi")
region = Rect2(192, 192, 64, 64)
[sub_resource type="AtlasTexture" id="AtlasTexture_t8xj5"]
atlas = ExtResource("2_ahfdi")
region = Rect2(256, 192, 64, 64)
[sub_resource type="AtlasTexture" id="AtlasTexture_uq6gh"]
atlas = ExtResource("2_ahfdi")
region = Rect2(320, 192, 64, 64)
[sub_resource type="AtlasTexture" id="AtlasTexture_q6wog"]
atlas = ExtResource("2_ahfdi")
region = Rect2(384, 192, 64, 64)
[sub_resource type="AtlasTexture" id="AtlasTexture_jcate"]
atlas = ExtResource("2_ahfdi")
region = Rect2(448, 192, 64, 64)
[sub_resource type="AtlasTexture" id="AtlasTexture_hl62h"]
atlas = ExtResource("2_ahfdi")
region = Rect2(512, 192, 64, 64)
[sub_resource type="AtlasTexture" id="AtlasTexture_60nri"]
atlas = ExtResource("2_ahfdi")
region = Rect2(576, 192, 64, 64)
[sub_resource type="AtlasTexture" id="AtlasTexture_60moo"]
atlas = ExtResource("2_ahfdi")
region = Rect2(0, 64, 64, 64)
[sub_resource type="AtlasTexture" id="AtlasTexture_pguj2"]
atlas = ExtResource("2_ahfdi")
region = Rect2(64, 64, 64, 64)
[sub_resource type="AtlasTexture" id="AtlasTexture_ybskn"]
atlas = ExtResource("2_ahfdi")
region = Rect2(128, 64, 64, 64)
[sub_resource type="AtlasTexture" id="AtlasTexture_el31c"]
atlas = ExtResource("2_ahfdi")
region = Rect2(192, 64, 64, 64)
[sub_resource type="AtlasTexture" id="AtlasTexture_7hu85"]
atlas = ExtResource("2_ahfdi")
region = Rect2(256, 64, 64, 64)
[sub_resource type="AtlasTexture" id="AtlasTexture_fuihh"]
atlas = ExtResource("2_ahfdi")
region = Rect2(320, 64, 64, 64)
[sub_resource type="AtlasTexture" id="AtlasTexture_mtyhi"]
atlas = ExtResource("2_ahfdi")
region = Rect2(384, 64, 64, 64)
[sub_resource type="AtlasTexture" id="AtlasTexture_sjkfo"]
atlas = ExtResource("2_ahfdi")
region = Rect2(448, 64, 64, 64)
[sub_resource type="AtlasTexture" id="AtlasTexture_htj0k"]
atlas = ExtResource("2_ahfdi")
region = Rect2(512, 64, 64, 64)
[sub_resource type="AtlasTexture" id="AtlasTexture_6hck2"]
atlas = ExtResource("2_ahfdi")
region = Rect2(576, 64, 64, 64)
[sub_resource type="AtlasTexture" id="AtlasTexture_0ksjp"]
atlas = ExtResource("3_kq38e")
region = Rect2(0, 0, 64, 64)
[sub_resource type="AtlasTexture" id="AtlasTexture_i4a22"]
atlas = ExtResource("3_kq38e")
region = Rect2(64, 0, 64, 64)
[sub_resource type="AtlasTexture" id="AtlasTexture_o8li6"]
atlas = ExtResource("3_kq38e")
region = Rect2(128, 0, 64, 64)
[sub_resource type="AtlasTexture" id="AtlasTexture_g0evx"]
atlas = ExtResource("3_kq38e")
region = Rect2(192, 0, 64, 64)
[sub_resource type="AtlasTexture" id="AtlasTexture_rdhnu"]
atlas = ExtResource("3_kq38e")
region = Rect2(256, 0, 64, 64)
[sub_resource type="AtlasTexture" id="AtlasTexture_84ews"]
atlas = ExtResource("3_kq38e")
region = Rect2(0, 128, 64, 64)
[sub_resource type="AtlasTexture" id="AtlasTexture_1xfj1"]
atlas = ExtResource("3_kq38e")
region = Rect2(64, 128, 64, 64)
[sub_resource type="AtlasTexture" id="AtlasTexture_trrl8"]
atlas = ExtResource("3_kq38e")
region = Rect2(128, 128, 64, 64)
[sub_resource type="AtlasTexture" id="AtlasTexture_lr5qx"]
atlas = ExtResource("3_kq38e")
region = Rect2(192, 128, 64, 64)
[sub_resource type="AtlasTexture" id="AtlasTexture_6ma40"]
atlas = ExtResource("3_kq38e")
region = Rect2(256, 128, 64, 64)
[sub_resource type="AtlasTexture" id="AtlasTexture_kwtft"]
atlas = ExtResource("3_kq38e")
region = Rect2(128, 0, 64, 64)
[sub_resource type="AtlasTexture" id="AtlasTexture_enu58"]
atlas = ExtResource("3_kq38e")
region = Rect2(0, 192, 64, 64)
[sub_resource type="AtlasTexture" id="AtlasTexture_7kdux"]
atlas = ExtResource("3_kq38e")
region = Rect2(64, 192, 64, 64)
[sub_resource type="AtlasTexture" id="AtlasTexture_bqnxo"]
atlas = ExtResource("3_kq38e")
region = Rect2(128, 192, 64, 64)
[sub_resource type="AtlasTexture" id="AtlasTexture_enu87"]
atlas = ExtResource("3_kq38e")
region = Rect2(192, 192, 64, 64)
[sub_resource type="AtlasTexture" id="AtlasTexture_2h6h5"]
atlas = ExtResource("3_kq38e")
region = Rect2(256, 192, 64, 64)
[sub_resource type="AtlasTexture" id="AtlasTexture_8fjfh"]
atlas = ExtResource("3_kq38e")
region = Rect2(0, 64, 64, 64)
[sub_resource type="AtlasTexture" id="AtlasTexture_vh8hy"]
atlas = ExtResource("3_kq38e")
region = Rect2(64, 64, 64, 64)
[sub_resource type="AtlasTexture" id="AtlasTexture_2rs53"]
atlas = ExtResource("3_kq38e")
region = Rect2(128, 64, 64, 64)
[sub_resource type="AtlasTexture" id="AtlasTexture_6qhe6"]
atlas = ExtResource("3_kq38e")
region = Rect2(192, 64, 64, 64)
[sub_resource type="AtlasTexture" id="AtlasTexture_5ch0i"]
atlas = ExtResource("3_kq38e")
region = Rect2(256, 64, 64, 64)
[sub_resource type="AtlasTexture" id="AtlasTexture_ugw68"]
atlas = ExtResource("4_ret1g")
region = Rect2(0, 0, 64, 64)
[sub_resource type="AtlasTexture" id="AtlasTexture_osbva"]
atlas = ExtResource("4_ret1g")
region = Rect2(64, 0, 64, 64)
[sub_resource type="AtlasTexture" id="AtlasTexture_e2rds"]
atlas = ExtResource("4_ret1g")
region = Rect2(128, 0, 64, 64)
[sub_resource type="AtlasTexture" id="AtlasTexture_8jpri"]
atlas = ExtResource("4_ret1g")
region = Rect2(192, 0, 64, 64)
[sub_resource type="AtlasTexture" id="AtlasTexture_p46gn"]
atlas = ExtResource("4_ret1g")
region = Rect2(256, 0, 64, 64)
[sub_resource type="AtlasTexture" id="AtlasTexture_tmsf0"]
atlas = ExtResource("4_ret1g")
region = Rect2(320, 0, 64, 64)
[sub_resource type="AtlasTexture" id="AtlasTexture_8jftq"]
atlas = ExtResource("4_ret1g")
region = Rect2(384, 0, 64, 64)
[sub_resource type="AtlasTexture" id="AtlasTexture_5xakg"]
atlas = ExtResource("4_ret1g")
region = Rect2(448, 0, 64, 64)
[sub_resource type="AtlasTexture" id="AtlasTexture_wjesj"]
atlas = ExtResource("4_ret1g")
region = Rect2(0, 128, 64, 64)
[sub_resource type="AtlasTexture" id="AtlasTexture_xicij"]
atlas = ExtResource("4_ret1g")
region = Rect2(64, 128, 64, 64)
[sub_resource type="AtlasTexture" id="AtlasTexture_wt4kn"]
atlas = ExtResource("4_ret1g")
region = Rect2(128, 128, 64, 64)
[sub_resource type="AtlasTexture" id="AtlasTexture_dfaft"]
atlas = ExtResource("4_ret1g")
region = Rect2(192, 128, 64, 64)
[sub_resource type="AtlasTexture" id="AtlasTexture_01vj4"]
atlas = ExtResource("4_ret1g")
region = Rect2(256, 128, 64, 64)
[sub_resource type="AtlasTexture" id="AtlasTexture_fevc3"]
atlas = ExtResource("4_ret1g")
region = Rect2(320, 128, 64, 64)
[sub_resource type="AtlasTexture" id="AtlasTexture_o8mkr"]
atlas = ExtResource("4_ret1g")
region = Rect2(384, 128, 64, 64)
[sub_resource type="AtlasTexture" id="AtlasTexture_khlie"]
atlas = ExtResource("4_ret1g")
region = Rect2(448, 128, 64, 64)
[sub_resource type="AtlasTexture" id="AtlasTexture_rt0q0"]
atlas = ExtResource("4_ret1g")
region = Rect2(0, 192, 64, 64)
[sub_resource type="AtlasTexture" id="AtlasTexture_b1gjj"]
atlas = ExtResource("4_ret1g")
region = Rect2(64, 192, 64, 64)
[sub_resource type="AtlasTexture" id="AtlasTexture_bt6g4"]
atlas = ExtResource("4_ret1g")
region = Rect2(128, 192, 64, 64)
[sub_resource type="AtlasTexture" id="AtlasTexture_jsjsv"]
atlas = ExtResource("4_ret1g")
region = Rect2(192, 192, 64, 64)
[sub_resource type="AtlasTexture" id="AtlasTexture_0l68k"]
atlas = ExtResource("4_ret1g")
region = Rect2(256, 192, 64, 64)
[sub_resource type="AtlasTexture" id="AtlasTexture_iimw2"]
atlas = ExtResource("4_ret1g")
region = Rect2(320, 192, 64, 64)
[sub_resource type="AtlasTexture" id="AtlasTexture_jlqmn"]
atlas = ExtResource("4_ret1g")
region = Rect2(384, 192, 64, 64)
[sub_resource type="AtlasTexture" id="AtlasTexture_gctn2"]
atlas = ExtResource("4_ret1g")
region = Rect2(448, 192, 64, 64)
[sub_resource type="AtlasTexture" id="AtlasTexture_x6bpc"]
atlas = ExtResource("4_ret1g")
region = Rect2(0, 64, 64, 64)
[sub_resource type="AtlasTexture" id="AtlasTexture_23if8"]
atlas = ExtResource("4_ret1g")
region = Rect2(64, 64, 64, 64)
[sub_resource type="AtlasTexture" id="AtlasTexture_1wf5b"]
atlas = ExtResource("4_ret1g")
region = Rect2(128, 64, 64, 64)
[sub_resource type="AtlasTexture" id="AtlasTexture_263iu"]
atlas = ExtResource("4_ret1g")
region = Rect2(192, 64, 64, 64)
[sub_resource type="AtlasTexture" id="AtlasTexture_gk0vp"]
atlas = ExtResource("4_ret1g")
region = Rect2(256, 64, 64, 64)
[sub_resource type="AtlasTexture" id="AtlasTexture_n30n6"]
atlas = ExtResource("4_ret1g")
region = Rect2(320, 64, 64, 64)
[sub_resource type="AtlasTexture" id="AtlasTexture_an4xw"]
atlas = ExtResource("4_ret1g")
region = Rect2(384, 64, 64, 64)
[sub_resource type="AtlasTexture" id="AtlasTexture_ohh0e"]
atlas = ExtResource("4_ret1g")
region = Rect2(448, 64, 64, 64)
[sub_resource type="SpriteFrames" id="SpriteFrames_05veu"]
animations = [{
"frames": [{
"duration": 1.0,
"texture": SubResource("AtlasTexture_u74be")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_hky14")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_1hmrm")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_icdnf")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_jpau6")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_pla0y")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_5ug5i")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_p0q1e")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_8gdmr")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_4gxlk")
}],
"loop": true,
"name": &"death_down",
"speed": 10.0
}, {
"frames": [{
"duration": 1.0,
"texture": SubResource("AtlasTexture_w642b")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_6tf61")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_354yo")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_wrhhh")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_5l6b7")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_ml8lr")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_flrsr")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_qr4cj")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_o5jey")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_1fjmf")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_3dxre")
}],
"loop": true,
"name": &"death_left",
"speed": 10.0
}, {
"frames": [{
"duration": 1.0,
"texture": SubResource("AtlasTexture_6mupu")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_cpqhb")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_vpjp1")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_pyvbc")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_t8xj5")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_uq6gh")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_q6wog")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_jcate")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_hl62h")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_60nri")
}],
"loop": true,
"name": &"death_right",
"speed": 10.0
}, {
"frames": [{
"duration": 1.0,
"texture": SubResource("AtlasTexture_60moo")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_pguj2")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_ybskn")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_el31c")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_7hu85")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_fuihh")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_mtyhi")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_sjkfo")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_htj0k")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_6hck2")
}],
"loop": true,
"name": &"death_up",
"speed": 10.0
}, {
"frames": [{
"duration": 1.0,
"texture": SubResource("AtlasTexture_0ksjp")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_i4a22")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_o8li6")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_g0evx")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_rdhnu")
}],
"loop": true,
"name": &"hurt_down",
"speed": 10.0
}, {
"frames": [{
"duration": 1.0,
"texture": SubResource("AtlasTexture_84ews")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_1xfj1")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_trrl8")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_lr5qx")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_6ma40")
}],
"loop": true,
"name": &"hurt_left",
"speed": 10.0
}, {
"frames": [{
"duration": 1.0,
"texture": SubResource("AtlasTexture_kwtft")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_enu58")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_7kdux")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_bqnxo")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_enu87")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_2h6h5")
}],
"loop": true,
"name": &"hurt_right",
"speed": 10.0
}, {
"frames": [{
"duration": 1.0,
"texture": SubResource("AtlasTexture_8fjfh")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_vh8hy")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_2rs53")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_6qhe6")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_5ch0i")
}],
"loop": true,
"name": &"hurt_up",
"speed": 10.0
}, {
"frames": [{
"duration": 1.0,
"texture": SubResource("AtlasTexture_ugw68")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_osbva")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_e2rds")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_8jpri")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_p46gn")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_tmsf0")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_8jftq")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_5xakg")
}],
"loop": true,
"name": &"walk_down",
"speed": 10.0
}, {
"frames": [{
"duration": 1.0,
"texture": SubResource("AtlasTexture_wjesj")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_xicij")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_wt4kn")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_dfaft")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_01vj4")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_fevc3")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_o8mkr")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_khlie")
}],
"loop": true,
"name": &"walk_left",
"speed": 10.0
}, {
"frames": [{
"duration": 1.0,
"texture": SubResource("AtlasTexture_rt0q0")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_b1gjj")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_bt6g4")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_jsjsv")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_0l68k")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_iimw2")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_jlqmn")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_gctn2")
}],
"loop": true,
"name": &"walk_right",
"speed": 10.0
}, {
"frames": [{
"duration": 1.0,
"texture": SubResource("AtlasTexture_x6bpc")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_23if8")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_1wf5b")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_263iu")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_gk0vp")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_n30n6")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_an4xw")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_ohh0e")
}],
"loop": true,
"name": &"walk_up",
"speed": 10.0
}]
[sub_resource type="CircleShape2D" id="CircleShape2D_1djsx"]
radius = 7.071068
[sub_resource type="CircleShape2D" id="CircleShape2D_odbmi"]
radius = 8.062258
[node name="FireSlime" type="CharacterBody2D" unique_id=1827403107]
script = ExtResource("1_88j2t")
metadata/_custom_type_script = "uid://c0uv02nt5ocvg"
[node name="AnimatedSprite2D" type="AnimatedSprite2D" parent="." unique_id=1151813585]
texture_filter = 1
sprite_frames = SubResource("SpriteFrames_05veu")
animation = &"walk_down"
[node name="CollisionShape2D" type="CollisionShape2D" parent="." unique_id=2114857632]
position = Vector2(0, 1)
shape = SubResource("CircleShape2D_1djsx")
[node name="Area2D" type="Area2D" parent="." unique_id=1305327123]
[node name="CollisionShape2D" type="CollisionShape2D" parent="Area2D" unique_id=762851125]
position = Vector2(0, 1)
shape = SubResource("CircleShape2D_odbmi")

View File

@ -1,11 +1,11 @@
extends Node2D
@onready var _timer_label: Label = $CanvasLayer/TimerLabel
@onready var _spawn_control = $SpawnControl
# Called when the node enters the scene tree for the first time.
func _ready():
MusicManager.play(preload("res://assets/music&sfx/music/ashveil-355633.mp3"))
# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta: float) -> void:
pass
func _process(_delta: float) -> void:
var t = int(_spawn_control.elapsed_time)
_timer_label.text = "%02d:%02d" % [t / 60, t % 60]

View File

@ -17,6 +17,9 @@
[ext_resource type="Script" uid="uid://ckv6prbe1o7s1" path="res://scripts/drop_manager.gd" id="10_vtaks"]
[ext_resource type="Script" uid="uid://pmmc7tivuuo4" path="res://scripts/perk_effects.gd" id="16_ca42v"]
[ext_resource type="Script" uid="uid://dm1sntwjrv3vl" path="res://scripts/level_up_manager.gd" id="16_rysoc"]
[ext_resource type="Script" uid="uid://duauc778wc3hd" path="res://scripts/pause_menu.gd" id="18_264po"]
[ext_resource type="FontFile" uid="uid://8v71dcws4q6o" path="res://assets/fonts/slkscre.ttf" id="19_1kice"]
[ext_resource type="Script" uid="uid://586y330mhx8" path="res://scripts/options_menu_ingame.gd" id="20_1kice"]
[ext_resource type="Texture2D" uid="uid://dp8o40ssuh8ip" path="res://assets/Tiny RPG Mana Soul GUI v1.0/20250421barB-Sheet.png" id="16_ssvqc"]
[sub_resource type="Resource" id="Resource_ssvqc"]
@ -2381,11 +2384,6 @@ anchors_preset = 0
offset_right = 40.0
offset_bottom = 40.0
script = ExtResource("6_p57ef")
spawn_entries = Array[ExtResource("6_ir15t")]([SubResource("Resource_ssvqc"), SubResource("Resource_264po")])
[node name="SpawnTimer" type="Timer" parent="." unique_id=1852920556]
wait_time = 0.2
autostart = true
[node name="Witch" parent="." unique_id=1188927311 instance=ExtResource("7_u5sy4")]
position = Vector2(304, 164)
@ -2438,6 +2436,24 @@ patch_margin_top = 5
patch_margin_right = 8
patch_margin_bottom = 6
[node name="TimerLabel" type="Label" parent="CanvasLayer" unique_id=1111111111]
anchors_preset = 5
anchor_left = 0.5
anchor_right = 0.5
offset_left = -60.0
offset_top = 31.0
offset_right = 60.0
offset_bottom = 55.0
grow_horizontal = 2
text = "00:00"
horizontal_alignment = 1
theme_override_fonts/font = ExtResource("19_1kice")
theme_override_font_sizes/font_size = 20
theme_override_colors/font_color = Color(1, 1, 1, 1)
theme_override_colors/font_shadow_color = Color(0, 0, 0, 1)
theme_override_constants/shadow_offset_x = 1
theme_override_constants/shadow_offset_y = 1
[node name="LevelUpManager" type="Control" parent="CanvasLayer" unique_id=292400493]
process_mode = 3
layout_mode = 3
@ -2475,4 +2491,154 @@ alignment = 1
[node name="PerkEffects" type="Node2D" parent="." unique_id=2027136639]
script = ExtResource("16_ca42v")
[connection signal="timeout" from="SpawnTimer" to="SpawnControl" method="_on_spawn_timer_timeout"]
[node name="PauseMenu" type="CanvasLayer" parent="." unique_id=551813974]
process_mode = 3
script = ExtResource("18_264po")
[node name="BackgroundRect" type="ColorRect" parent="PauseMenu" unique_id=2031198327]
z_index = -1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
color = Color(0, 0, 0, 0.47058824)
[node name="VBoxContainer" type="VBoxContainer" parent="PauseMenu" unique_id=1987220146]
z_index = 1
anchors_preset = 8
anchor_left = 0.5
anchor_top = 0.5
anchor_right = 0.5
anchor_bottom = 0.5
offset_left = -308.5
offset_top = -106.0
offset_right = 308.5
offset_bottom = 106.0
grow_horizontal = 2
grow_vertical = 2
theme_override_constants/separation = 50
alignment = 1
[node name="Label" type="Label" parent="PauseMenu/VBoxContainer" unique_id=1321477768]
layout_mode = 2
theme_override_fonts/font = ExtResource("19_1kice")
theme_override_font_sizes/font_size = 64
text = "Pause"
horizontal_alignment = 1
[node name="ContinueButton" type="Button" parent="PauseMenu/VBoxContainer" unique_id=760316781]
custom_minimum_size = Vector2(200, 45)
layout_mode = 2
theme_override_fonts/font = ExtResource("19_1kice")
theme_override_font_sizes/font_size = 32
text = "Continue"
[node name="OptionsButton" type="Button" parent="PauseMenu/VBoxContainer" unique_id=857989621]
custom_minimum_size = Vector2(200, 45)
layout_mode = 2
theme_override_fonts/font = ExtResource("19_1kice")
theme_override_font_sizes/font_size = 32
text = "Options"
[node name="QuitButton" type="Button" parent="PauseMenu/VBoxContainer" unique_id=1745540926]
custom_minimum_size = Vector2(200, 45)
layout_mode = 2
theme_override_fonts/font = ExtResource("19_1kice")
theme_override_font_sizes/font_size = 32
text = "Quit"
[node name="OptionsMenu" type="Control" parent="PauseMenu" unique_id=1962611001]
layout_mode = 3
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
script = ExtResource("20_1kice")
[node name="VBoxContainer" type="VBoxContainer" parent="PauseMenu/OptionsMenu" unique_id=494075248]
z_index = 2
layout_mode = 1
anchors_preset = 8
anchor_left = 0.5
anchor_top = 0.5
anchor_right = 0.5
anchor_bottom = 0.5
offset_left = -308.5
offset_top = -106.0
offset_right = 308.5
offset_bottom = 106.0
grow_horizontal = 2
grow_vertical = 2
theme_override_constants/separation = 50
alignment = 1
[node name="Label" type="Label" parent="PauseMenu/OptionsMenu/VBoxContainer" unique_id=2020901742]
layout_mode = 2
theme_override_fonts/font = ExtResource("19_1kice")
theme_override_font_sizes/font_size = 64
text = "Options"
horizontal_alignment = 1
[node name="HBoxContainer" type="HBoxContainer" parent="PauseMenu/OptionsMenu/VBoxContainer" unique_id=1131620527]
custom_minimum_size = Vector2(300, 0)
layout_mode = 2
alignment = 1
[node name="Label" type="Label" parent="PauseMenu/OptionsMenu/VBoxContainer/HBoxContainer" unique_id=1154725043]
custom_minimum_size = Vector2(150, 0)
layout_mode = 2
theme_override_fonts/font = ExtResource("19_1kice")
theme_override_font_sizes/font_size = 32
text = "Music Volume"
[node name="HSlider" type="HSlider" parent="PauseMenu/OptionsMenu/VBoxContainer/HBoxContainer" unique_id=880316772]
custom_minimum_size = Vector2(300, 30)
layout_mode = 2
[node name="HBoxContainer3" type="HBoxContainer" parent="PauseMenu/OptionsMenu/VBoxContainer" unique_id=240142399]
custom_minimum_size = Vector2(300, 0)
layout_mode = 2
alignment = 1
[node name="Label" type="Label" parent="PauseMenu/OptionsMenu/VBoxContainer/HBoxContainer3" unique_id=154714416]
custom_minimum_size = Vector2(150, 0)
layout_mode = 2
theme_override_fonts/font = ExtResource("19_1kice")
theme_override_font_sizes/font_size = 32
text = "SFX Volume"
[node name="HSlider" type="HSlider" parent="PauseMenu/OptionsMenu/VBoxContainer/HBoxContainer3" unique_id=173892539]
custom_minimum_size = Vector2(300, 30)
layout_mode = 2
[node name="HBoxContainer2" type="HBoxContainer" parent="PauseMenu/OptionsMenu/VBoxContainer" unique_id=1323966021]
custom_minimum_size = Vector2(300, 0)
layout_mode = 2
alignment = 1
[node name="Label" type="Label" parent="PauseMenu/OptionsMenu/VBoxContainer/HBoxContainer2" unique_id=1472770579]
custom_minimum_size = Vector2(150, 0)
layout_mode = 2
theme_override_fonts/font = ExtResource("19_1kice")
theme_override_font_sizes/font_size = 32
text = "Fullscreen"
[node name="CheckBox" type="CheckBox" parent="PauseMenu/OptionsMenu/VBoxContainer/HBoxContainer2" unique_id=2108676279]
layout_mode = 2
[node name="BackButton" type="Button" parent="PauseMenu/OptionsMenu/VBoxContainer" unique_id=141581932]
custom_minimum_size = Vector2(200, 45)
layout_mode = 2
theme_override_fonts/font = ExtResource("19_1kice")
theme_override_font_sizes/font_size = 32
text = "Back"
[connection signal="pressed" from="PauseMenu/VBoxContainer/ContinueButton" to="PauseMenu" method="_on_continue_button_pressed"]
[connection signal="pressed" from="PauseMenu/VBoxContainer/OptionsButton" to="PauseMenu" method="_on_options_button_pressed"]
[connection signal="pressed" from="PauseMenu/VBoxContainer/QuitButton" to="PauseMenu" method="_on_quit_button_pressed"]
[connection signal="value_changed" from="PauseMenu/OptionsMenu/VBoxContainer/HBoxContainer/HSlider" to="PauseMenu/OptionsMenu" method="_on_h_slider_value_changed"]
[connection signal="value_changed" from="PauseMenu/OptionsMenu/VBoxContainer/HBoxContainer3/HSlider" to="PauseMenu/OptionsMenu" method="_on_h2_slider_value_changed"]
[connection signal="toggled" from="PauseMenu/OptionsMenu/VBoxContainer/HBoxContainer2/CheckBox" to="PauseMenu/OptionsMenu" method="_on_check_box_toggled"]
[connection signal="pressed" from="PauseMenu/OptionsMenu/VBoxContainer/BackButton" to="PauseMenu/OptionsMenu" method="_on_back_button_pressed"]

View File

@ -0,0 +1,33 @@
[gd_scene format=3 uid="uid://oegpflgwf17e"]
[ext_resource type="Script" uid="uid://dpj26ryawjq02" path="res://scripts/throwing_knive.gd" id="2_knive"]
[ext_resource type="Texture2D" uid="uid://pot4k8a6lxd0" path="res://assets/weapons/knvie.png" id="2_tyd64"]
[sub_resource type="AtlasTexture" id="AtlasTexture_frs86"]
atlas = ExtResource("2_tyd64")
region = Rect2(0, 0, 32, 32)
[sub_resource type="SpriteFrames" id="SpriteFrames_t4gbw"]
animations = [{
"frames": [{
"duration": 1.0,
"texture": SubResource("AtlasTexture_frs86")
}],
"loop": true,
"name": &"default",
"speed": 5.0
}]
[sub_resource type="RectangleShape2D" id="RectangleShape2D_1ss1s"]
size = Vector2(15, 7)
[node name="ThrowingKnive" type="Area2D" unique_id=882877238]
script = ExtResource("2_knive")
[node name="AnimatedSprite2D" type="AnimatedSprite2D" parent="." unique_id=164559800]
texture_filter = 1
sprite_frames = SubResource("SpriteFrames_t4gbw")
[node name="CollisionShape2D" type="CollisionShape2D" parent="." unique_id=886320879]
position = Vector2(0.5, -0.5)
shape = SubResource("RectangleShape2D_1ss1s")

View File

@ -0,0 +1,6 @@
extends Resource
class_name SpawnStage
@export var time_start: float = 0.0
@export var time_end: float = -1.0 # -1 = forever
@export var entries: Array[StageEntry]

View File

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

View File

@ -0,0 +1,8 @@
extends Resource
class_name StageEntry
@export var enemy: PackedScene
@export var count_at_start: int = 0
@export var count_at_end: int = 20
@export var min_interval: float = 0.3
@export var max_spawns: int = -1 # -1 = unlimited

View File

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

View File

@ -3,7 +3,7 @@ extends EnemyBase
func _ready() -> void:
super()
speed = 0.1
speed = 15.0
hits_remaining = 2
$Area2D.body_entered.connect(_on_area_2d_body_entered)

View File

@ -67,11 +67,10 @@ func _process(delta: float) -> void:
pass
func _chase_witch() -> void:
var direction = Vector2(witch.global_position - global_position)
var direction = Vector2(witch.global_position - global_position).normalized()
if direction != Vector2.ZERO:
last_direction = direction
velocity = direction * speed
velocity = direction * speed
if direction == Vector2.ZERO:
animated_sprite_2d.play("idle")

View File

@ -0,0 +1,17 @@
extends EnemyBase
func _ready() -> void:
super()
speed = 15.0
hits_remaining = 3
$Area2D.body_entered.connect(_on_area_2d_body_entered)
func _process(delta: float) -> void:
if is_dying or is_hurt:
return
_chase_witch()
func _on_area_2d_body_entered(body: Node2D) -> void:
if body == player:
hit()

View File

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

View File

@ -6,12 +6,17 @@ func _ready():
music_player = AudioStreamPlayer.new()
music_player.bus = "Music"
add_child(music_player)
music_player.process_mode = Node.PROCESS_MODE_ALWAYS
music_player.finished.connect(_on_music_finished)
func play(stream: AudioStream):
if music_player.stream == stream and music_player.playing:
return # läuft schon, nichts tun
return
music_player.stream = stream
music_player.play()
func stop():
music_player.stop()
func _on_music_finished():
music_player.play()

View File

@ -0,0 +1,53 @@
extends Control
var sfx_preview = preload("res://assets/music&sfx/sfx/hit2.wav")
func _ready():
hide()
# Music Slider
$VBoxContainer/HBoxContainer/HSlider.min_value = 0.0
$VBoxContainer/HBoxContainer/HSlider.max_value = 1.0
$VBoxContainer/HBoxContainer/HSlider.step = 0.01
# Aktuellen Bus-Wert als Startwert setzen
var bus_idx = AudioServer.get_bus_index("Music")
$VBoxContainer/HBoxContainer/HSlider.value = db_to_linear(AudioServer.get_bus_volume_db(bus_idx))
# SFX Slider
$VBoxContainer/HBoxContainer3/HSlider.min_value = 0.0
$VBoxContainer/HBoxContainer3/HSlider.max_value = 1.0
$VBoxContainer/HBoxContainer3/HSlider.step = 0.01
# Aktuellen Bus-Wert als Startwert setzen
var sfx_idx = AudioServer.get_bus_index("SFX")
$VBoxContainer/HBoxContainer3/HSlider.value = db_to_linear(AudioServer.get_bus_volume_db(sfx_idx))
func _on_back_button_pressed() -> void:
hide()
get_parent().get_node("VBoxContainer").show()
func _on_check_box_toggled(toggled_on: bool) -> void:
if toggled_on:
DisplayServer.window_set_mode(DisplayServer.WINDOW_MODE_FULLSCREEN)
else:
DisplayServer.window_set_mode(DisplayServer.WINDOW_MODE_WINDOWED)
func _on_h_slider_value_changed(value: float) -> void:
var bus_idx = AudioServer.get_bus_index("Music")
AudioServer.set_bus_volume_db(bus_idx, linear_to_db(value))
func _on_h2_slider_value_changed(value: float) -> void:
var bus_idx = AudioServer.get_bus_index("SFX")
AudioServer.set_bus_volume_db(bus_idx, linear_to_db(value))
# Vorschau-Sound abspielen
var preview = AudioStreamPlayer.new()
add_child(preview)
preview.stream = sfx_preview
preview.bus = "SFX"
preview.play()
await preview.finished
preview.queue_free()
func _unhandled_input(event):
if event.is_action_pressed("ui_cancel") and visible:
_on_back_button_pressed()

View File

@ -0,0 +1 @@
uid://586y330mhx8

View File

@ -0,0 +1,26 @@
extends CanvasLayer
func _ready():
hide()
func _unhandled_input(event):
if event.is_action_pressed("ui_cancel"):
if $OptionsMenu.visible:
return
toggle_pause()
func toggle_pause():
var paused = not get_tree().paused
get_tree().paused = paused
visible = paused
func _on_continue_button_pressed() -> void:
toggle_pause()
func _on_quit_button_pressed() -> void:
get_tree().quit()
func _on_options_button_pressed() -> void:
$VBoxContainer.hide()
$OptionsMenu.show()

View File

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

View File

@ -3,35 +3,43 @@ extends Node2D
@onready var witch = get_node("/root/Game/Witch")
@onready var player = get_node("/root/Game/Player")
var fireball = preload("res://scenes/fireball.tscn")
var throwing_knife = preload("res://scenes/throwing_knive.tscn")
var cauldron
var available_perks: Array[Perk] = []
var fireball_aoe_enabled = false
# Called when the node enters the scene tree for the first time.
var throwing_knife_enabled = false
var throwing_knife_cooldown: float = 2.0
var _knife_timer: float = 0.0
func _ready() -> void:
cauldron = witch.get_node("CauldronBar")
var dsh = Perk.new()
dsh.name = "Doppelter Shuriken"
dsh.description = "Wirft zwei Shurikens\n statt einem"
dsh.name = "Double Shuriken"
dsh.description = "Throw two shurikens instead of one"
dsh.effect = double_shuriken
available_perks.append(dsh)
var faoe = Perk.new()
faoe.name = "AOE-Fireball"
faoe.description = "Feuerbälle erzeugen\n eine Explosion\n bei Berührung"
faoe.name = "AOE Fireball"
faoe.description = "Fireballs spawn an explosion on contact"
faoe.effect = fireball_aoe
available_perks.append(faoe)
var bexp = Perk.new()
bexp.name = "Brewing-Explosion"
bexp.description = "Die Hexe erzeugt\n eine Explosion am\n Ende des Brauens"
bexp.name = "Brew Explosion"
bexp.description = "The Witch casts an explosion on finishing a brew"
bexp.effect = brew_explosion
available_perks.append(bexp)
var tk = Perk.new()
tk.name = "Throwing Knife"
tk.description = "Automatically throw a knife at the nearest enemy every second"
tk.effect = enable_throwing_knife
available_perks.append(tk)
pass # Replace with function body.
# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta: float) -> void:
pass
if throwing_knife_enabled:
_knife_timer += delta
if _knife_timer >= throwing_knife_cooldown:
_knife_timer = 0.0
_shoot_throwing_knife()
func double_shuriken():
witch.shuriken_count = 2
@ -42,3 +50,25 @@ func fireball_aoe():
func brew_explosion():
cauldron.brew_explosion = true
func enable_throwing_knife():
throwing_knife_enabled = true
var upg = Perk.new()
upg.name = "Knife Cooldown"
upg.description = "Reduce throwing knife cooldown by 0.2s (min 1s)"
upg.effect = knife_cooldown_upgrade
available_perks.append(upg)
func knife_cooldown_upgrade():
throwing_knife_cooldown = maxf(1.0, throwing_knife_cooldown - 0.2)
if throwing_knife_cooldown > 1.0:
var upg = Perk.new()
upg.name = "Knife Cooldown"
upg.description = "Reduce throwing knife cooldown by 0.2s (min 1s)"
upg.effect = knife_cooldown_upgrade
available_perks.append(upg)
func _shoot_throwing_knife() -> void:
var knife = throwing_knife.instantiate()
knife.global_position = witch.global_position
witch.get_parent().add_child(knife)

View File

@ -6,7 +6,7 @@ extends EnemyBase
# Called every frame. 'delta' is the elapsed time since the previous frame.+
func _ready() -> void:
super()
speed = 0.1
speed = 15.0
func _process(delta: float) -> void:
if is_dying:

View File

@ -1,72 +1,117 @@
extends Control
var up_left
var down_right
var up_right
var down_left
var viewport_rect
var elapsed_time = 0.0
@export var spawn_entries: Array[SpawnEntry]
var up_left: Vector2
var down_right: Vector2
var up_right: Vector2
var down_left: Vector2
var elapsed_time: float = 0.0
const STAGES_JSON = "res://data/spawn_stages.json"
var stages: Array[SpawnStage] = []
# _state keys: Vector2i(stage_idx, entry_idx)
# values: { "timer": float, "alive": int }
var _state: Dictionary = {}
func _ready() -> void:
var camera: Camera2D = get_parent().get_node("Camera2D")
var viewport_size = get_viewport_rect().size
var world_size = viewport_size / camera.zoom
var world_origin = camera.global_position # anchor_mode = 0 → top-left corner
var world_origin = camera.global_position
up_left = world_origin
down_right = world_origin + world_size
up_right = Vector2(down_right.x, up_left.y)
down_left = Vector2(up_left.x, down_right.y)
_load_stages(STAGES_JSON)
for si in stages.size():
for ei in stages[si].entries.size():
_state[Vector2i(si, ei)] = { "timer": 0.0, "alive": 0, "spawned_total": 0 }
func _load_stages(path: String) -> void:
var file = FileAccess.open(path, FileAccess.READ)
if file == null:
push_error("spawn_control: cannot open " + path)
return
var data = JSON.parse_string(file.get_as_text())
if not data is Array:
push_error("spawn_control: invalid JSON in " + path)
return
for sd in data:
var stage = SpawnStage.new()
stage.time_start = float(sd["time_start"])
stage.time_end = float(sd["time_end"])
for ed in sd["entries"]:
var entry = StageEntry.new()
entry.enemy = load(ed["enemy"])
entry.count_at_start = int(ed["count_at_start"])
entry.count_at_end = int(ed["count_at_end"])
entry.min_interval = float(ed["min_interval"])
entry.max_spawns = int(ed.get("max_spawns", -1))
stage.entries.append(entry)
stages.append(stage)
func get_spawn_position() -> Vector2:
var side = randi() % 4
var spawn_x
var spawn_y
var spawn_x: float
var spawn_y: float
if side == 0:
# oben
spawn_x = randf_range(up_left.x, up_right.x)
spawn_y = up_left.y
elif side == 1:
# rechts
spawn_x = up_right.x
spawn_y = randf_range(up_right.y, down_right.y)
elif side == 2:
#unten
spawn_x = randf_range(up_left.x, up_right.x)
spawn_y = down_left.y
elif side == 3:
#links
else:
spawn_x = up_left.x
spawn_y = randf_range(up_right.y, down_right.y)
return Vector2(spawn_x, spawn_y)
# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta: float) -> void:
elapsed_time += delta
pass
func spawn_enemy() -> void:
var sum_weight = 0.0
var available = []
for entry in spawn_entries:
if entry.min_time <= elapsed_time:
available.append(entry)
sum_weight += entry.weight
var roll = randf() * sum_weight
var winner = null
for entry in available:
roll -= entry.weight
if roll <= 0:
winner = entry
break
if winner == null:
return
var enemy = winner.enemy.instantiate()
for si in stages.size():
var stage: SpawnStage = stages[si]
if elapsed_time < stage.time_start:
continue
if stage.time_end != -1.0 and elapsed_time > stage.time_end:
continue
var t: float
if stage.time_end == -1.0:
t = 1.0
else:
t = clamp(
(elapsed_time - stage.time_start) / (stage.time_end - stage.time_start),
0.0, 1.0
)
for ei in stage.entries.size():
var entry: StageEntry = stage.entries[ei]
var state: Dictionary = _state[Vector2i(si, ei)]
if entry.max_spawns != -1 and state["spawned_total"] >= entry.max_spawns:
continue
var target: int = roundi(lerpf(float(entry.count_at_start), float(entry.count_at_end), t))
var deficit: int = target - state["alive"]
if deficit <= 0:
continue
state["timer"] -= delta
if state["timer"] <= 0.0:
state["timer"] = max(entry.min_interval, 1.0 / float(deficit))
_spawn_one(entry, state)
func _spawn_one(entry: StageEntry, state: Dictionary) -> void:
var enemy = entry.enemy.instantiate()
enemy.global_position = get_spawn_position()
state["alive"] += 1
state["spawned_total"] += 1
enemy.tree_exited.connect(func(): state["alive"] -= 1)
add_child(enemy)
func _on_spawn_timer_timeout() -> void:
spawn_enemy()
pass # Replace with function body.

View File

@ -0,0 +1,24 @@
extends ProjectileBase
var _target_enemy: Node = null
func _ready() -> void:
super()
speed = 400.0
var witch = get_node("/root/Game/Witch")
_target_enemy = witch.get_nearest_enemy(witch.global_position, _knife_filter)
if _target_enemy == null:
queue_free()
return
_target_enemy.add_to_group("knife_targeted")
tree_exiting.connect(_on_knife_exiting)
var dir = global_position.direction_to(_target_enemy.global_position)
rotation = dir.angle()
launch(_target_enemy.global_position)
func _knife_filter(enemy: Node) -> bool:
return not enemy.is_dying and not enemy.is_hurt and not enemy.is_in_group("knife_targeted")
func _on_knife_exiting() -> void:
if is_instance_valid(_target_enemy) and _target_enemy.is_in_group("knife_targeted"):
_target_enemy.remove_from_group("knife_targeted")

View File

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

View File

@ -43,10 +43,12 @@ func shoot_shuriken():
get_parent().add_child(sh)
await get_tree().create_timer(0.2).timeout
func get_nearest_enemy(from: Vector2) -> Node:
func get_nearest_enemy(from: Vector2, filter: Callable = Callable()) -> Node:
var nearest = null
var min_distance = INF
for enemy in get_tree().get_nodes_in_group("enemies"):
if filter.is_valid() and not filter.call(enemy):
continue
var dist = from.distance_to(enemy.global_position)
if dist < min_distance:
min_distance = dist