Compare commits

...

20 Commits

Author SHA1 Message Date
Jaro Winkelhausen 8a9614b17a made tornado area bigger (#14)
Co-authored-by: 3002102 <3002102@stud.th-mannheim.de>
Reviewed-on: #14
2026-04-24 02:01:10 +02:00
Jaro Winkelhausen c7e1afdc37 feat/tornado (#13)
Co-authored-by: Jaro <jaro@MacBook.local>
Co-authored-by: 3002102 <3002102@stud.th-mannheim.de>
Reviewed-on: #13
2026-04-24 01:56:22 +02:00
Jaro Winkelhausen c959b0d3e5 feat/spellbook (#12)
Co-authored-by: Jaro <jaro@MacBook.local>
Co-authored-by: 3002102 <3002102@stud.th-mannheim.de>
Reviewed-on: #12
2026-04-21 17:17:35 +02:00
Jaro Winkelhausen 3f6e76c154 added an actual hp/damage system to the witch and enemies game over screen is still missing the game just restarts (#11)
Co-authored-by: Jaro <jaro@MacBook.local>
Reviewed-on: #11
2026-04-21 13:16:58 +02:00
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
Artur 452325a0b4 fixed explosion calculation and finished cards + xp bar 2026-04-15 17:22:15 +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
Artur David 681471259b improved card size 2026-04-15 16:09:46 +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
Artur c2cbeba20c created card ui 2026-04-15 07:11:06 +02:00
75 changed files with 2442 additions and 122 deletions

BIN
.DS_Store vendored

Binary file not shown.

3
.gitignore vendored
View File

@ -2,5 +2,8 @@
.godot/
/android/
# macOS metadata
.DS_Store
# Claude Code
.claude/worktrees/

BIN
assets/.DS_Store vendored

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,14 @@
Pixel Art License
Copyright © OceansCurse 2026 — All rights reserved.
You are free to:
- Use these assets in any personal or commercial project (including games, apps, merchandise, etc.).
- Modify, adapt, and create derivative works from these assets.
You are not permitted to:
- Redistribute, resell, or re-upload these assets (or substantial portions/modified versions) as standalone files, asset packs, or listings on itch.io, other marketplaces, or elsewhere.
- Present or claim these assets (original or modified) as your own original creation in a way that removes my authorship.
Attribution is not required, but always appreciated (e.g., "Assets by OceansCurse on itch.io").
These terms do not affect your rights under fair use or other applicable law.

Binary file not shown.

After

Width:  |  Height:  |  Size: 551 B

View File

@ -0,0 +1,40 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://blotgjvb5lg5n"
path="res://.godot/imported/books_blue_gem.png-6b9e1efe847341054172f4dc841820d4.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://assets/books_set_2/books_blue_gem.png"
dest_files=["res://.godot/imported/books_blue_gem.png-6b9e1efe847341054172f4dc841820d4.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

Binary file not shown.

After

Width:  |  Height:  |  Size: 537 B

View File

@ -0,0 +1,40 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://b1dpo1suawep6"
path="res://.godot/imported/books_crimson_gem.png-e8e082c355c0dfd58d6abd9b647c9d64.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://assets/books_set_2/books_crimson_gem.png"
dest_files=["res://.godot/imported/books_crimson_gem.png-e8e082c355c0dfd58d6abd9b647c9d64.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

Binary file not shown.

After

Width:  |  Height:  |  Size: 472 B

View File

@ -0,0 +1,40 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://b0p1bbqie3r44"
path="res://.godot/imported/books_cross.png-35551b7d8d063fdb0725cd59a672b335.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://assets/books_set_2/books_cross.png"
dest_files=["res://.godot/imported/books_cross.png-35551b7d8d063fdb0725cd59a672b335.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

Binary file not shown.

After

Width:  |  Height:  |  Size: 621 B

View File

@ -0,0 +1,40 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://jghgdp2kyjo7"
path="res://.godot/imported/books_eye.png-0b5ed65a09665cddbdbac80092f229ee.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://assets/books_set_2/books_eye.png"
dest_files=["res://.godot/imported/books_eye.png-0b5ed65a09665cddbdbac80092f229ee.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

Binary file not shown.

After

Width:  |  Height:  |  Size: 542 B

View File

@ -0,0 +1,40 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://colq7wi3ti117"
path="res://.godot/imported/books_green_gem.png-1a6532ce505dc88ac93cf48f05352ebe.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://assets/books_set_2/books_green_gem.png"
dest_files=["res://.godot/imported/books_green_gem.png-1a6532ce505dc88ac93cf48f05352ebe.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

Binary file not shown.

After

Width:  |  Height:  |  Size: 583 B

View File

@ -0,0 +1,40 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://cq4qf7to1wg0m"
path="res://.godot/imported/books_health_potion.png-f8c3182e75c659e8cd07cbcee2ba8296.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://assets/books_set_2/books_health_potion.png"
dest_files=["res://.godot/imported/books_health_potion.png-f8c3182e75c659e8cd07cbcee2ba8296.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

Binary file not shown.

After

Width:  |  Height:  |  Size: 578 B

View File

@ -0,0 +1,40 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://lo5ocyv4wo3e"
path="res://.godot/imported/books_jewel.png-81cbdb01e058151fa333b7a570f883b8.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://assets/books_set_2/books_jewel.png"
dest_files=["res://.godot/imported/books_jewel.png-81cbdb01e058151fa333b7a570f883b8.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

Binary file not shown.

After

Width:  |  Height:  |  Size: 545 B

View File

@ -0,0 +1,40 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://1pr5rqdnpnw5"
path="res://.godot/imported/books_mana_potion.png-e9b0c98b6782a5538a4f682f9d61384f.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://assets/books_set_2/books_mana_potion.png"
dest_files=["res://.godot/imported/books_mana_potion.png-e9b0c98b6782a5538a4f682f9d61384f.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

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -0,0 +1,40 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://dlygc6jakfapg"
path="res://.godot/imported/books_pentagram.png-3e29e3d9c342d860aa7f6d22635f65db.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://assets/books_set_2/books_pentagram.png"
dest_files=["res://.godot/imported/books_pentagram.png-3e29e3d9c342d860aa7f6d22635f65db.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

Binary file not shown.

After

Width:  |  Height:  |  Size: 566 B

View File

@ -0,0 +1,40 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://cogqoxfqsnvv1"
path="res://.godot/imported/books_poison.png-3e8beaf0e04a26a46016fddeb0daf0f8.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://assets/books_set_2/books_poison.png"
dest_files=["res://.godot/imported/books_poison.png-3e8beaf0e04a26a46016fddeb0daf0f8.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

Binary file not shown.

After

Width:  |  Height:  |  Size: 548 B

View File

@ -0,0 +1,40 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://ryhfe1a3haxf"
path="res://.godot/imported/books_purple_gem.png-a017fe601493fdc75182a2e7b6cf68cb.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://assets/books_set_2/books_purple_gem.png"
dest_files=["res://.godot/imported/books_purple_gem.png-a017fe601493fdc75182a2e7b6cf68cb.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

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

View File

@ -0,0 +1,40 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://bnlacakjmdnp1"
path="res://.godot/imported/books_set_2_preview.png-e47aaf46da7c1d64191f8dfb0958de3a.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://assets/books_set_2/books_set_2_preview.png"
dest_files=["res://.godot/imported/books_set_2_preview.png-e47aaf46da7c1d64191f8dfb0958de3a.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

Binary file not shown.

After

Width:  |  Height:  |  Size: 458 B

View File

@ -0,0 +1,40 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://dm3wtcchfipcf"
path="res://.godot/imported/books_upside_down_cross.png-f374141fa42ba8d66998f6c556ae5908.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://assets/books_set_2/books_upside_down_cross.png"
dest_files=["res://.godot/imported/books_upside_down_cross.png-f374141fa42ba8d66998f6c556ae5908.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

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,101 @@
[gd_scene format=3 uid="uid://bbhpa50ef6702"]
[ext_resource type="Script" uid="uid://dw5y2tp34fxys" path="res://scripts/perk_card.gd" id="1_t8gqh"]
[ext_resource type="Texture2D" uid="uid://duo145bmwho8d" path="res://assets/UI assets pack 2/UI books & more.png" id="2_nlhlf"]
[ext_resource type="FontFile" uid="uid://cq0jx2aapggkg" path="res://assets/fonts/slkscrb.ttf" id="3_n4umd"]
[ext_resource type="FontFile" uid="uid://brooj0hba7650" path="res://assets/fonts/slkscr.ttf" id="4_40ty6"]
[ext_resource type="Texture2D" uid="uid://cdktimg5axaxj" path="res://assets/Fire Pixel Bullet 16x16/All_Fire_Bullet_Pixel_16x16_01.png" id="4_nlhlf"]
[sub_resource type="AtlasTexture" id="AtlasTexture_fgk3h"]
atlas = ExtResource("2_nlhlf")
region = Rect2(561, 17, 46, 62)
[sub_resource type="LabelSettings" id="LabelSettings_qag4p"]
line_spacing = 5.0
font = ExtResource("3_n4umd")
font_size = 12
[sub_resource type="AtlasTexture" id="AtlasTexture_n4umd"]
atlas = ExtResource("4_nlhlf")
region = Rect2(258, 241, 25, 14)
[sub_resource type="LabelSettings" id="LabelSettings_ni87r"]
font = ExtResource("4_40ty6")
font_size = 11
[node name="PerkCard" type="Control" unique_id=1471811151]
custom_minimum_size = Vector2(200, 300)
layout_mode = 3
anchors_preset = 0
script = ExtResource("1_t8gqh")
[node name="Card" type="TextureRect" parent="." unique_id=1832247473]
texture_filter = 1
custom_minimum_size = Vector2(200, 300)
layout_mode = 0
offset_right = 40.0
offset_bottom = 40.0
texture = SubResource("AtlasTexture_fgk3h")
[node name="Name" type="Label" parent="Card" unique_id=2006873472]
layout_mode = 1
anchors_preset = 5
anchor_left = 0.5
anchor_right = 0.5
offset_left = -50.5
offset_top = 43.0
offset_right = 50.5
offset_bottom = 92.0
grow_horizontal = 2
text = "Zweizeilige
Überschrift
"
label_settings = SubResource("LabelSettings_qag4p")
horizontal_alignment = 1
[node name="TextureRect" type="TextureRect" parent="Card/Name" unique_id=2128840891]
layout_mode = 1
anchors_preset = 7
anchor_left = 0.5
anchor_top = 1.0
anchor_right = 0.5
anchor_bottom = 1.0
offset_left = -24.5
offset_top = -10.0
offset_right = 24.5
offset_bottom = 19.0
grow_horizontal = 2
grow_vertical = 0
texture = SubResource("AtlasTexture_n4umd")
[node name="Description" type="Label" parent="Card" unique_id=859816848]
layout_mode = 1
anchors_preset = 7
anchor_left = 0.5
anchor_top = 1.0
anchor_right = 0.5
anchor_bottom = 1.0
offset_left = -65.0
offset_top = -176.0
offset_right = 69.0
offset_bottom = -43.0
grow_horizontal = 2
grow_vertical = 0
text = "Text in Zeile Eins
Text in Zeile Eins
Text in Zeile Eins
Text in Zeile Eins
Text in Zeile Zwei
Text in Zeile Drei
Text in Zeile Vier
Text in Zeile Fünf"
label_settings = SubResource("LabelSettings_ni87r")
horizontal_alignment = 1
autowrap_mode = 2
[node name="Button" type="Button" parent="." unique_id=1274377333]
layout_mode = 0
offset_right = 200.0
offset_bottom = 300.0
[connection signal="pressed" from="Button" to="." method="_on_button_pressed"]

View File

@ -589,7 +589,7 @@ animations = [{
}],
"loop": false,
"name": &"hurt_down",
"speed": 10.0
"speed": 20.0
}, {
"frames": [{
"duration": 1.0,
@ -609,7 +609,7 @@ animations = [{
}],
"loop": false,
"name": &"hurt_left",
"speed": 10.0
"speed": 20.0
}, {
"frames": [{
"duration": 1.0,
@ -629,7 +629,7 @@ animations = [{
}],
"loop": false,
"name": &"hurt_right",
"speed": 10.0
"speed": 20.0
}, {
"frames": [{
"duration": 1.0,
@ -649,7 +649,7 @@ animations = [{
}],
"loop": false,
"name": &"hurt_up",
"speed": 10.0
"speed": 20.0
}, {
"frames": [{
"duration": 1.0,

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": false,
"name": &"hurt_down",
"speed": 20.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": 20.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": 20.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": 20.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 = &"hurt_up"
[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

@ -20,6 +20,7 @@
[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"]
script = ExtResource("6_ir15t")
@ -2383,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)
@ -2409,24 +2405,88 @@ script = ExtResource("10_vtaks")
[node name="CanvasLayer" type="CanvasLayer" parent="." unique_id=1323249211]
[node name="ProgressBar" type="ProgressBar" parent="CanvasLayer" unique_id=825658619]
offset_right = 607.0
anchors_preset = 5
anchor_left = 0.5
anchor_right = 0.5
offset_left = -303.5
offset_right = 303.5
offset_bottom = 27.0
grow_horizontal = 2
max_value = 5.0
step = 1.0
show_percentage = false
[node name="NinePatchRect" type="NinePatchRect" parent="CanvasLayer/ProgressBar" unique_id=1364517669]
texture_filter = 1
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
offset_left = -6.5
offset_top = -1.0
offset_right = 5.5
offset_bottom = 2.0
grow_horizontal = 2
grow_vertical = 2
texture = ExtResource("16_ssvqc")
draw_center = false
region_rect = Rect2(0, 0, 95, 15)
patch_margin_left = 7
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
anchors_preset = 0
offset_right = 40.0
offset_bottom = 40.0
anchors_preset = 5
anchor_left = 0.5
anchor_right = 0.5
grow_horizontal = 2
script = ExtResource("16_rysoc")
[node name="ColorRect" type="ColorRect" parent="CanvasLayer/LevelUpManager" unique_id=1319513730]
layout_mode = 1
offset_left = -656.0
offset_top = -9.0
offset_right = 642.0
offset_bottom = 728.0
color = Color(0, 0, 0, 0.0627451)
[node name="HBoxContainer" type="HBoxContainer" parent="CanvasLayer/LevelUpManager" unique_id=957625333]
layout_mode = 0
offset_right = 40.0
offset_bottom = 40.0
custom_minimum_size = Vector2(1000, 400)
layout_mode = 1
anchors_preset = 8
anchor_left = 0.5
anchor_top = 0.5
anchor_right = 0.5
anchor_bottom = 0.5
offset_left = -20.0
offset_top = 350.0
offset_right = 20.0
offset_bottom = 390.0
grow_horizontal = 2
grow_vertical = 2
theme_override_constants/separation = 50
alignment = 1
[node name="PerkEffects" type="Node2D" parent="." unique_id=2027136639]
script = ExtResource("16_ca42v")
@ -2575,7 +2635,6 @@ theme_override_fonts/font = ExtResource("19_1kice")
theme_override_font_sizes/font_size = 32
text = "Back"
[connection signal="timeout" from="SpawnTimer" to="SpawnControl" method="_on_spawn_timer_timeout"]
[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"]

View File

@ -7,6 +7,7 @@
[ext_resource type="Texture2D" uid="uid://cxddvfs2wfwcl" path="res://assets/Slime1/Without_shadow/Slime1_Idle_without_shadow.png" id="3_rrqju"]
[ext_resource type="Texture2D" uid="uid://b2bmw70co6noy" path="res://assets/Slime1/Without_shadow/Slime1_Walk_without_shadow.png" id="4_wyhst"]
[ext_resource type="Texture2D" uid="uid://bshpjl3w1n0y1" path="res://assets/Slime1/With_shadow/Slime1_Death_with_shadow.png" id="5_gstla"]
[ext_resource type="Texture2D" uid="uid://dwpyocmvqptui" path="res://assets/Slime1/With_shadow/Slime1_Hurt_with_shadow.png" id="7_v5wyi"]
[sub_resource type="Resource" id="Resource_gstla"]
script = ExtResource("2_2npkn")
@ -238,6 +239,86 @@ region = Rect2(256, 0, 64, 64)
atlas = ExtResource("3_rrqju")
region = Rect2(320, 0, 64, 64)
[sub_resource type="AtlasTexture" id="AtlasTexture_p5vph"]
atlas = ExtResource("7_v5wyi")
region = Rect2(0, 0, 64, 64)
[sub_resource type="AtlasTexture" id="AtlasTexture_4vxow"]
atlas = ExtResource("7_v5wyi")
region = Rect2(64, 0, 64, 64)
[sub_resource type="AtlasTexture" id="AtlasTexture_ymo5x"]
atlas = ExtResource("7_v5wyi")
region = Rect2(128, 0, 64, 64)
[sub_resource type="AtlasTexture" id="AtlasTexture_v338d"]
atlas = ExtResource("7_v5wyi")
region = Rect2(192, 0, 64, 64)
[sub_resource type="AtlasTexture" id="AtlasTexture_vn1yr"]
atlas = ExtResource("7_v5wyi")
region = Rect2(256, 0, 64, 64)
[sub_resource type="AtlasTexture" id="AtlasTexture_il7ig"]
atlas = ExtResource("7_v5wyi")
region = Rect2(0, 128, 64, 64)
[sub_resource type="AtlasTexture" id="AtlasTexture_5baf8"]
atlas = ExtResource("7_v5wyi")
region = Rect2(64, 128, 64, 64)
[sub_resource type="AtlasTexture" id="AtlasTexture_mmuop"]
atlas = ExtResource("7_v5wyi")
region = Rect2(128, 128, 64, 64)
[sub_resource type="AtlasTexture" id="AtlasTexture_7fqim"]
atlas = ExtResource("7_v5wyi")
region = Rect2(192, 128, 64, 64)
[sub_resource type="AtlasTexture" id="AtlasTexture_0ivba"]
atlas = ExtResource("7_v5wyi")
region = Rect2(256, 128, 64, 64)
[sub_resource type="AtlasTexture" id="AtlasTexture_0f1a3"]
atlas = ExtResource("7_v5wyi")
region = Rect2(0, 192, 64, 64)
[sub_resource type="AtlasTexture" id="AtlasTexture_3qxe4"]
atlas = ExtResource("7_v5wyi")
region = Rect2(64, 192, 64, 64)
[sub_resource type="AtlasTexture" id="AtlasTexture_8tsuk"]
atlas = ExtResource("7_v5wyi")
region = Rect2(128, 192, 64, 64)
[sub_resource type="AtlasTexture" id="AtlasTexture_uxjht"]
atlas = ExtResource("7_v5wyi")
region = Rect2(192, 192, 64, 64)
[sub_resource type="AtlasTexture" id="AtlasTexture_72t0a"]
atlas = ExtResource("7_v5wyi")
region = Rect2(256, 192, 64, 64)
[sub_resource type="AtlasTexture" id="AtlasTexture_e0x1h"]
atlas = ExtResource("7_v5wyi")
region = Rect2(0, 64, 64, 64)
[sub_resource type="AtlasTexture" id="AtlasTexture_eodiq"]
atlas = ExtResource("7_v5wyi")
region = Rect2(64, 64, 64, 64)
[sub_resource type="AtlasTexture" id="AtlasTexture_d4gio"]
atlas = ExtResource("7_v5wyi")
region = Rect2(128, 64, 64, 64)
[sub_resource type="AtlasTexture" id="AtlasTexture_q2l3s"]
atlas = ExtResource("7_v5wyi")
region = Rect2(192, 64, 64, 64)
[sub_resource type="AtlasTexture" id="AtlasTexture_3l0w5"]
atlas = ExtResource("7_v5wyi")
region = Rect2(256, 64, 64, 64)
[sub_resource type="AtlasTexture" id="AtlasTexture_fur4c"]
atlas = ExtResource("4_wyhst")
region = Rect2(0, 0, 64, 64)
@ -568,6 +649,86 @@ animations = [{
}, {
"frames": [{
"duration": 1.0,
"texture": SubResource("AtlasTexture_p5vph")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_4vxow")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_ymo5x")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_v338d")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_vn1yr")
}],
"loop": true,
"name": &"hurt_down",
"speed": 20.0
}, {
"frames": [{
"duration": 1.0,
"texture": SubResource("AtlasTexture_il7ig")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_5baf8")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_mmuop")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_7fqim")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_0ivba")
}],
"loop": true,
"name": &"hurt_left",
"speed": 20.0
}, {
"frames": [{
"duration": 1.0,
"texture": SubResource("AtlasTexture_0f1a3")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_3qxe4")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_8tsuk")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_uxjht")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_72t0a")
}],
"loop": true,
"name": &"hurt_right",
"speed": 20.0
}, {
"frames": [{
"duration": 1.0,
"texture": SubResource("AtlasTexture_e0x1h")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_eodiq")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_d4gio")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_q2l3s")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_3l0w5")
}],
"loop": true,
"name": &"hurt_up",
"speed": 20.0
}, {
"frames": [{
"duration": 1.0,
"texture": SubResource("AtlasTexture_fur4c")
}, {
"duration": 1.0,
@ -696,7 +857,7 @@ drop_table = Array[ExtResource("2_2npkn")]([SubResource("Resource_gstla")])
[node name="AnimatedSprite2D" type="AnimatedSprite2D" parent="." unique_id=752118449]
texture_filter = 1
sprite_frames = SubResource("SpriteFrames_cbi0b")
animation = &"walk_right"
animation = &"hurt_up"
[node name="CollisionShape2D" type="CollisionShape2D" parent="." unique_id=769710804]
position = Vector2(0, 1)

View File

@ -0,0 +1,35 @@
[gd_scene format=3 uid="uid://s5m6whnjl3cv"]
[ext_resource type="Script" uid="uid://c6w6hhayguqoj" path="res://scripts/spellbook.gd" id="1_f8wgx"]
[ext_resource type="Texture2D" uid="uid://dlygc6jakfapg" path="res://assets/books_set_2/books_pentagram.png" id="2_g1ouv"]
[sub_resource type="AtlasTexture" id="AtlasTexture_md3wj"]
atlas = ExtResource("2_g1ouv")
region = Rect2(0, 0, 32, 32)
[sub_resource type="SpriteFrames" id="SpriteFrames_qgan7"]
animations = [{
"frames": [{
"duration": 1.0,
"texture": SubResource("AtlasTexture_md3wj")
}],
"loop": true,
"name": &"default",
"speed": 10.0
}]
[sub_resource type="RectangleShape2D" id="RectangleShape2D_i8red"]
size = Vector2(22.5, 26.5)
[node name="Spellbook" type="Area2D" unique_id=1926827672]
script = ExtResource("1_f8wgx")
[node name="AnimatedSprite2D" type="AnimatedSprite2D" parent="." unique_id=1402601698]
texture_filter = 1
scale = Vector2(0.5, 0.5)
sprite_frames = SubResource("SpriteFrames_qgan7")
[node name="CollisionShape2D" type="CollisionShape2D" parent="." unique_id=609912720]
position = Vector2(-0.625, -0.625)
scale = Vector2(0.5, 0.5)
shape = SubResource("RectangleShape2D_i8red")

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")

152
scenes/tornado.tscn 100644
View File

@ -0,0 +1,152 @@
[gd_scene format=3 uid="uid://byqfrmwg0mi3y"]
[ext_resource type="Script" uid="uid://cikwl1ib4puyt" path="res://scripts/tornado.gd" id="1_shahy"]
[ext_resource type="Texture2D" uid="uid://c50u48fy7jtd" path="res://assets/Free Effect Bullet Impact Explosion 32x32 V1/Purple Effect Bullet Impact Explosion 32x32.png" id="2_3gxx4"]
[sub_resource type="AtlasTexture" id="AtlasTexture_vctls"]
atlas = ExtResource("2_3gxx4")
region = Rect2(192, 0, 32, 32)
[sub_resource type="AtlasTexture" id="AtlasTexture_2nlrq"]
atlas = ExtResource("2_3gxx4")
region = Rect2(224, 0, 32, 32)
[sub_resource type="AtlasTexture" id="AtlasTexture_yxxy5"]
atlas = ExtResource("2_3gxx4")
region = Rect2(256, 0, 32, 32)
[sub_resource type="AtlasTexture" id="AtlasTexture_mdjqp"]
atlas = ExtResource("2_3gxx4")
region = Rect2(288, 0, 32, 32)
[sub_resource type="AtlasTexture" id="AtlasTexture_shahy"]
atlas = ExtResource("2_3gxx4")
region = Rect2(608, 160, 32, 32)
[sub_resource type="AtlasTexture" id="AtlasTexture_3gxx4"]
atlas = ExtResource("2_3gxx4")
region = Rect2(576, 160, 32, 32)
[sub_resource type="AtlasTexture" id="AtlasTexture_2nqqh"]
atlas = ExtResource("2_3gxx4")
region = Rect2(544, 160, 32, 32)
[sub_resource type="AtlasTexture" id="AtlasTexture_g5iue"]
atlas = ExtResource("2_3gxx4")
region = Rect2(512, 160, 32, 32)
[sub_resource type="AtlasTexture" id="AtlasTexture_c1uv1"]
atlas = ExtResource("2_3gxx4")
region = Rect2(512, 416, 32, 32)
[sub_resource type="AtlasTexture" id="AtlasTexture_ido5e"]
atlas = ExtResource("2_3gxx4")
region = Rect2(512, 448, 32, 32)
[sub_resource type="AtlasTexture" id="AtlasTexture_e7sy5"]
atlas = ExtResource("2_3gxx4")
region = Rect2(512, 384, 32, 32)
[sub_resource type="AtlasTexture" id="AtlasTexture_0xwcu"]
atlas = ExtResource("2_3gxx4")
region = Rect2(544, 352, 32, 32)
[sub_resource type="AtlasTexture" id="AtlasTexture_jd32a"]
atlas = ExtResource("2_3gxx4")
region = Rect2(576, 352, 32, 32)
[sub_resource type="AtlasTexture" id="AtlasTexture_p68fy"]
atlas = ExtResource("2_3gxx4")
region = Rect2(608, 352, 32, 32)
[sub_resource type="AtlasTexture" id="AtlasTexture_1h6yc"]
atlas = ExtResource("2_3gxx4")
region = Rect2(576, 384, 32, 32)
[sub_resource type="AtlasTexture" id="AtlasTexture_3p0aw"]
atlas = ExtResource("2_3gxx4")
region = Rect2(608, 384, 32, 32)
[sub_resource type="SpriteFrames" id="SpriteFrames_2nqqh"]
animations = [{
"frames": [{
"duration": 1.0,
"texture": SubResource("AtlasTexture_vctls")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_2nlrq")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_yxxy5")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_mdjqp")
}],
"loop": true,
"name": &"default",
"speed": 10.0
}, {
"frames": [{
"duration": 1.0,
"texture": SubResource("AtlasTexture_shahy")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_3gxx4")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_2nqqh")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_g5iue")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_c1uv1")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_ido5e")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_e7sy5")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_0xwcu")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_jd32a")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_p68fy")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_1h6yc")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_3p0aw")
}],
"loop": false,
"name": &"explosion",
"speed": 10.0
}]
[sub_resource type="CapsuleShape2D" id="CapsuleShape2D_g5iue"]
radius = 25.0
height = 50.0
[sub_resource type="CircleShape2D" id="CircleShape2D_07hm3"]
radius = 54.0
[node name="Tornado" type="Area2D" unique_id=892015509]
script = ExtResource("1_shahy")
[node name="AnimatedSprite2D" type="AnimatedSprite2D" parent="." unique_id=1613801541]
texture_filter = 1
scale = Vector2(1.5, 1.5)
sprite_frames = SubResource("SpriteFrames_2nqqh")
frame_progress = 0.68617874
[node name="ExplosionCollision" type="CollisionShape2D" parent="." unique_id=1019771818]
shape = SubResource("CapsuleShape2D_g5iue")
disabled = true
[node name="TornadoArea" type="CollisionShape2D" parent="." unique_id=1356386666]
shape = SubResource("CircleShape2D_07hm3")

View File

@ -3,4 +3,5 @@ class_name Perk
@export var name: String
@export var description: String
@export var icon: Texture2D = null
var effect: Callable

View File

@ -2,8 +2,9 @@ extends Area2D
class_name ProjectileBase
@export var size: float
@export var damage: int = 5
var speed = 200
@export var element: String
@export var element: String
var direction: Vector2
func _ready() -> void:
@ -20,7 +21,7 @@ func launch(target: Vector2):
func _on_body_entered(body: Node2D) -> void:
if body.is_in_group("enemies"):
body.hit()
body.take_damage(damage)
queue_free()
func _remove():

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

@ -1,17 +1,18 @@
extends EnemyBase
func _ready() -> void:
super()
speed = 0.1
hits_remaining = 2
speed = 15.0
max_hp = 25
hp = max_hp
$Area2D.body_entered.connect(_on_area_2d_body_entered)
func _process(delta: float) -> void:
super._process(delta)
if is_dying or is_hurt:
return
_chase_witch()
func _on_area_2d_body_entered(body: Node2D) -> void:
if body == player:
hit()
take_damage(player.damage)

View File

@ -82,15 +82,16 @@ func progres_bar(fruit):
func brew(fruits):
is_brewing = true
var unique = get_unique_fruits()
await ignite_cauldrons()
if fruits == [2, 2, 4]:
var apple_count = fruits.count(2)
var grape_count = fruits.count(4)
if apple_count == 2 and grape_count == 1:
witch.shoot_fire_swirl()
elif unique.has(2) and unique.size() == 1:
elif apple_count == 3:
witch.shoot_fireballs()
elif unique.has(4) and unique.size() == 1:
witch.shoot_shuriken()
elif unique.has(2) and unique.has(4) and unique.size() == 2:
elif grape_count == 3:
witch.shoot_tornado()
elif apple_count == 1 and grape_count == 2:
witch.shoot_fireballs()
witch.shoot_shuriken()
reset_texture()

View File

@ -4,9 +4,14 @@ extends CharacterBody2D
@onready var animated_sprite_2d: AnimatedSprite2D = $AnimatedSprite2D
@export var drop_table: Array[DropTable]
@export var damage: int = 2
@export var max_hp: int = 10
var is_dying = false
var is_hurt = false
var hits_remaining = 1
var hp: int
var _touching_witch: bool = false
var speed
var witch
var player
@ -21,6 +26,17 @@ func _ready() -> void:
witch = get_node("/root/Game/Witch")
player = get_node("/root/Game/Player")
animated_sprite_2d.sprite_frames = animated_sprite_2d.sprite_frames.duplicate()
hp = max_hp
$Area2D.body_entered.connect(_on_base_body_entered)
$Area2D.body_exited.connect(_on_base_body_exited)
func _on_base_body_entered(body: Node2D) -> void:
if body == witch:
_touching_witch = true
func _on_base_body_exited(body: Node2D) -> void:
if body == witch:
_touching_witch = false
func die():
is_dying = true
@ -41,37 +57,41 @@ func die():
await animated_sprite_2d.animation_finished
queue_free()
func hit() -> void:
func take_damage(amount: int) -> void:
if is_dying or is_hurt:
return
hits_remaining -= 1
if hits_remaining <= 0:
hp -= amount
if hp <= 0:
die()
else:
_play_hurt()
func hit() -> void:
take_damage(1)
func _play_hurt() -> void:
is_hurt = true
var hurt_anim: String
if abs(last_direction.x) >= abs(last_direction.y):
hurt_anim = "hurt_left" if last_direction.x < 0 else "hurt_right"
else:
hurt_anim = "hurt_up" if last_direction.y < 0 else "hurt_down"
if not animated_sprite_2d.sprite_frames.has_animation(hurt_anim):
return
is_hurt = true
animated_sprite_2d.sprite_frames.set_animation_loop(hurt_anim, false)
animated_sprite_2d.play(hurt_anim)
await animated_sprite_2d.animation_finished
await get_tree().create_timer(0.25, true).timeout
is_hurt = false
# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta: float) -> void:
pass
if _touching_witch and not is_dying:
witch.take_damage(damage)
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

@ -1,11 +1,12 @@
extends Area2D
@export var damage: int = 15
# Called when the node enters the scene tree for the first time.
func _ready():
await get_tree().physics_frame
for body in get_overlapping_bodies():
if body.is_in_group("enemies"):
body.hit()
body.take_damage(damage)
await $AnimatedSprite2D.animation_finished
queue_free()

View File

@ -0,0 +1,18 @@
extends EnemyBase
func _ready() -> void:
super()
speed = 15.0
max_hp = 50
hp = max_hp
$Area2D.body_entered.connect(_on_area_2d_body_entered)
func _process(delta: float) -> void:
super._process(delta)
if is_dying or is_hurt:
return
_chase_witch()
func _on_area_2d_body_entered(body: Node2D) -> void:
if body == player:
take_damage(player.damage)

View File

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

View File

@ -15,9 +15,10 @@ const DIRS := [
func _on_body_entered(body: Node2D) -> void:
if body.is_in_group("enemies"):
body.hit()
body.take_damage(damage)
func _ready() -> void:
damage = 6
if _is_spread_child:
super()
return

View File

@ -2,14 +2,19 @@ extends ProjectileBase
var fireball_aoe = false
var explosion_scene = preload("res://scenes/explosion.tscn")
@onready var perk_effects = get_node("/root/Game/PerkEffects")# Called when the node enters the scene tree for the first time.
@onready var perk_effects = get_node("/root/Game/PerkEffects")
func _ready() -> void:
super()
damage = 8
func _on_body_entered(body: Node2D) -> void:
fireball_aoe = perk_effects.fireball_aoe_enabled
if body.is_in_group("enemies"):
body.hit()
body.take_damage(damage)
if fireball_aoe:
var boom = explosion_scene.instantiate()
boom.global_position = global_position
get_parent().add_child(boom)
get_parent().call_deferred("add_child", boom)
queue_free()

View File

@ -2,7 +2,9 @@ extends Control
@onready var perk_effects = get_node("/root/Game/PerkEffects")
var perks
@onready var perkCard = preload("res://scenes/PerkCard.tscn")
# Called when the node enters the scene tree for the first time.
func _ready() -> void:
perks = perk_effects.available_perks
@ -17,18 +19,23 @@ func _process(delta: float) -> void:
func show_perks():
if perks.is_empty():
return
var tween = create_tween()
tween.tween_property($ColorRect, "color:a", 0.6, 0.3)
get_tree().paused = true
var shuffled = perks.duplicate()
shuffled.shuffle()
var chosen = shuffled.slice(0, 3)
for x in chosen:
var button = Button.new()
button.text = x.name + "\n" + x.description
button.pressed.connect(func(): select_perk(x))
$HBoxContainer.add_child(button)
var card = perkCard.instantiate()
$HBoxContainer.add_child(card)
card.setup(x, func(): select_perk(x))
func select_perk(perk):
perk.effect.call()
get_tree().paused = false
perks.erase(perk)
for child in $HBoxContainer.get_children(): child.queue_free()
var tween = create_tween()
tween.tween_property($ColorRect, "color:a", 0.0, 0.3)
await tween.finished

View File

@ -0,0 +1,42 @@
extends Control
@export var icon: Texture2D
# Called when the node enters the scene tree for the first time.
var on_select: Callable
func setup(perk: Perk, select: Callable):
$Button.modulate.a = 0
$Card/Name.text = perk.name
$Card/Description.text = perk.description
if perk.icon != null:
$Card/Name/TextureRect.texture = perk.icon
animate_in()
$Button.modulate.a = 0.3
$Button.mouse_entered.connect(func(): $Button.modulate.a = 0.6)
$Button.mouse_exited.connect(func(): $Button.modulate.a = 0.3)
on_select = select
func _on_button_pressed() -> void:
await animate_out()
on_select.call()
pass # Replace with function body.
func animate_in():
await get_tree().process_frame
var start_y = global_position.y + 500
var end_y = global_position.y
global_position.y = start_y
var tween = create_tween()
tween.tween_property(self, "global_position:y", end_y, 0.3).set_ease(Tween.EASE_OUT).set_trans(Tween.TRANS_QUAD)
func animate_out():
var start_y = global_position.y
var end_y = global_position.y - 500
global_position.y = start_y
var tween = create_tween()
tween.tween_property(self, "global_position:y", end_y, 0.3).set_ease(Tween.EASE_IN).set_trans(Tween.TRANS_QUAD)
await tween.finished

View File

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

View File

@ -3,42 +3,163 @@ 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 throwing_knife_count: int = 1
var _knife_timer: float = 0.0
var spellbook_scene = preload("res://scenes/spellbook.tscn")
var spellbook_count: int = 0
var spellbook_damage: int = 12
var spellbook_speed: float = 1.5
const SPELLBOOK_RADIUS: float = 60.0
var _spellbook_angle: float = 0.0
var _spellbooks: Array = []
func _ready() -> void:
cauldron = witch.get_node("CauldronBar")
var dsh = Perk.new()
dsh.name = "Doppelter Shuriken"
dsh.description = "Wirft zwei Shurikens 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 eine Explosion 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 eine Explosion am 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)
pass # Replace with function body.
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)
var sb = Perk.new()
sb.name = "Spellbook"
sb.description = "A spellbook orbits the witch, dealing 12 damage to enemies it touches"
sb.effect = unlock_spellbook
available_perks.append(sb)
# 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()
if spellbook_count > 0:
_spellbook_angle += spellbook_speed * delta
for i in range(_spellbooks.size()):
var offset = (TAU / _spellbooks.size()) * i
_spellbooks[i].global_position = witch.global_position + Vector2(cos(_spellbook_angle + offset), sin(_spellbook_angle + offset)) * SPELLBOOK_RADIUS
func double_shuriken():
witch.shuriken_count = 2
func fireball_aoe():
fireball_aoe_enabled = true
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)
var ek = Perk.new()
ek.name = "Extra Knife"
ek.description = "Throw one additional knife per attack (max 3)"
ek.effect = extra_knife
available_perks.append(ek)
func extra_knife():
throwing_knife_count = min(throwing_knife_count + 1, 3)
if throwing_knife_count < 3:
var ek = Perk.new()
ek.name = "Extra Knife"
ek.description = "Throw one additional knife per attack (max 3)"
ek.effect = extra_knife
available_perks.append(ek)
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:
for i in range(throwing_knife_count):
var knife = throwing_knife.instantiate()
knife.global_position = witch.global_position
witch.get_parent().add_child(knife)
func unlock_spellbook() -> void:
spellbook_count = 1
_rebuild_spellbooks()
var eb = Perk.new()
eb.name = "Extra Book"
eb.description = "Add another spellbook (max 5)"
eb.effect = extra_book
available_perks.append(eb)
var fo = Perk.new()
fo.name = "Faster Orbit"
fo.description = "Spellbooks orbit the witch faster"
fo.effect = faster_orbit
available_perks.append(fo)
var bd = Perk.new()
bd.name = "Book Damage"
bd.description = "Spellbooks deal 4 more damage"
bd.effect = book_damage
available_perks.append(bd)
func extra_book() -> void:
spellbook_count = min(spellbook_count + 1, 5)
_rebuild_spellbooks()
if spellbook_count < 5:
var eb = Perk.new()
eb.name = "Extra Book"
eb.description = "Add another spellbook (max 5)"
eb.effect = extra_book
available_perks.append(eb)
func faster_orbit() -> void:
spellbook_speed += 0.5
var fo = Perk.new()
fo.name = "Faster Orbit"
fo.description = "Spellbooks orbit the witch faster"
fo.effect = faster_orbit
available_perks.append(fo)
func book_damage() -> void:
spellbook_damage += 4
for book in _spellbooks:
book.damage = spellbook_damage
var bd = Perk.new()
bd.name = "Book Damage"
bd.description = "Spellbooks deal 4 more damage"
bd.effect = book_damage
available_perks.append(bd)
func _rebuild_spellbooks() -> void:
for book in _spellbooks:
book.queue_free()
_spellbooks.clear()
for i in range(spellbook_count):
var book = spellbook_scene.instantiate()
book.damage = spellbook_damage
witch.get_parent().add_child(book)
_spellbooks.append(book)

View File

@ -1,9 +1,10 @@
extends CharacterBody2D
@onready var animated_sprite_2d: AnimatedSprite2D = $AnimatedSprite2D
var current_xp = 0
var max_xp =5
var max_xp = 5
var level = 1
var speed = 200 # speed in pixels/sec
var speed = 200
var damage: int = 10
func _physics_process(delta):
var direction = Input.get_vector("ui_left", "ui_right", "ui_up", "ui_down")

View File

@ -6,6 +6,7 @@ var enemies_hit = 0
func _ready() -> void:
speed = 500
super()
damage = 5
var first = get_nearest_enemy(global_position)
if first == null:
queue_free()
@ -15,7 +16,7 @@ func _ready() -> void:
func _on_body_entered(body: Node2D) -> void:
if body.is_in_group("enemies") and not body.is_hurt and not body.is_dying:
enemies_hit += 1
body.hit()
body.take_damage(damage)
if enemies_hit == 20:
queue_free()
else:

View File

@ -1,22 +1,19 @@
extends EnemyBase
# Called when the node enters the scene tree for the first time.
# Called every frame. 'delta' is the elapsed time since the previous frame.+
func _ready() -> void:
super()
speed = 0.1
speed = 15.0
max_hp = 10
hp = max_hp
func _process(delta: float) -> void:
if is_dying:
super._process(delta)
if is_dying or is_hurt:
return
_chase_witch()
pass
func _on_area_2d_body_entered(body: Node2D) -> void:
if is_dying:
return
if body == player:
die()
pass # Replace with function body.
take_damage(player.damage)

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,18 @@
extends Area2D
var damage: int = 12
var _hit_cooldowns: Dictionary = {}
func _ready() -> void:
body_entered.connect(_on_body_entered)
func _process(delta: float) -> void:
for enemy in _hit_cooldowns.keys():
_hit_cooldowns[enemy] -= delta
if _hit_cooldowns[enemy] <= 0.0:
_hit_cooldowns.erase(enemy)
func _on_body_entered(body: Node2D) -> void:
if body.is_in_group("enemies") and not _hit_cooldowns.has(body):
body.take_damage(damage)
_hit_cooldowns[body] = 0.8

View File

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

View File

@ -0,0 +1,25 @@
extends ProjectileBase
var _target_enemy: Node = null
func _ready() -> void:
super()
speed = 400.0
damage = 12
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

47
scripts/tornado.gd 100644
View File

@ -0,0 +1,47 @@
extends Area2D
@export var pull_duration: float = 1.2
@export var pull_strength: float = 140.0
@export var explosion_damage: int = 50
@onready var animated_sprite_2d: AnimatedSprite2D = $AnimatedSprite2D
@onready var tornado_area: CollisionShape2D = $TornadoArea
@onready var explosion_collision: CollisionShape2D = $ExplosionCollision
var _is_pulling := true
var _damaged_enemies: Array[Node] = []
func _ready() -> void:
tornado_area.disabled = false
explosion_collision.disabled = true
if animated_sprite_2d.sprite_frames.has_animation("default"):
animated_sprite_2d.play("default")
await get_tree().create_timer(pull_duration).timeout
_explode()
func _physics_process(delta: float) -> void:
if not _is_pulling:
return
for enemy in get_overlapping_bodies():
if not enemy.is_in_group("enemies"):
continue
if enemy.is_dying:
continue
enemy.global_position = enemy.global_position.move_toward(global_position, pull_strength * delta)
func _explode() -> void:
_is_pulling = false
tornado_area.disabled = true
explosion_collision.disabled = false
if animated_sprite_2d.sprite_frames.has_animation("explosion"):
animated_sprite_2d.play("explosion")
await get_tree().physics_frame
for body in get_overlapping_bodies():
if body.is_in_group("enemies") and not _damaged_enemies.has(body):
body.take_damage(explosion_damage)
_damaged_enemies.append(body)
if animated_sprite_2d.sprite_frames.has_animation("explosion"):
await animated_sprite_2d.animation_finished
else:
await get_tree().create_timer(0.35).timeout
queue_free()

View File

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

View File

@ -1,15 +1,42 @@
extends CharacterBody2D
signal health_changed(current_hp: int, max_hp: int)
var camera
var is_casting = false
var fireball = preload("res://scenes/fireball.tscn")
var shuriken = preload("res://scenes/shuriken.tscn")
var fire_swirl = preload("res://scenes/fire_swirl.tscn")
var tornado = preload("res://scenes/tornado.tscn")
var shuriken_count = 1
var max_hp: int = 100
var current_hp: int = 100
var is_invincible: bool = false
const HP_BAR_WIDTH = 20
const HP_BAR_HEIGHT = 3
var _hp_bar_fill: ColorRect
func _ready() -> void:
$CauldronBar.witch = self
camera = get_node("/root/Game/Camera2D")
_setup_hp_bar()
func _setup_hp_bar() -> void:
var bg = ColorRect.new()
bg.color = Color(0.15, 0.15, 0.15, 0.85)
bg.size = Vector2(HP_BAR_WIDTH, HP_BAR_HEIGHT)
bg.position = Vector2(-HP_BAR_WIDTH / 2.0, 18)
add_child(bg)
_hp_bar_fill = ColorRect.new()
_hp_bar_fill.color = Color(0.85, 0.1, 0.1, 1.0)
_hp_bar_fill.size = Vector2(HP_BAR_WIDTH, HP_BAR_HEIGHT)
_hp_bar_fill.position = Vector2(-HP_BAR_WIDTH / 2.0, 18)
add_child(_hp_bar_fill)
func _update_hp_bar() -> void:
_hp_bar_fill.size.x = HP_BAR_WIDTH * (float(current_hp) / float(max_hp))
func _physics_process(delta: float) -> void:
# Add the gravity.
@ -42,11 +69,34 @@ func shoot_shuriken():
sh.global_position = global_position
get_parent().add_child(sh)
await get_tree().create_timer(0.2).timeout
func shoot_tornado():
var target = get_nearest_enemy(global_position)
var tw = tornado.instantiate()
tw.global_position = target.global_position if target != null else global_position
get_parent().add_child(tw)
camera.shake(0.3, 0.8)
func get_nearest_enemy(from: Vector2) -> Node:
func take_damage(amount: int) -> void:
if is_invincible:
return
current_hp -= amount
current_hp = max(current_hp, 0)
health_changed.emit(current_hp, max_hp)
_update_hp_bar()
if current_hp <= 0:
get_tree().call_deferred("reload_current_scene")
return
is_invincible = true
await get_tree().create_timer(1.0).timeout
is_invincible = false
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