Compare commits

..

18 Commits

Author SHA1 Message Date
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
68 changed files with 2224 additions and 116 deletions

BIN
.DS_Store vendored

Binary file not shown.

BIN
assets/.DS_Store vendored

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, "loop": false,
"name": &"hurt_down", "name": &"hurt_down",
"speed": 10.0 "speed": 20.0
}, { }, {
"frames": [{ "frames": [{
"duration": 1.0, "duration": 1.0,
@ -609,7 +609,7 @@ animations = [{
}], }],
"loop": false, "loop": false,
"name": &"hurt_left", "name": &"hurt_left",
"speed": 10.0 "speed": 20.0
}, { }, {
"frames": [{ "frames": [{
"duration": 1.0, "duration": 1.0,
@ -629,7 +629,7 @@ animations = [{
}], }],
"loop": false, "loop": false,
"name": &"hurt_right", "name": &"hurt_right",
"speed": 10.0 "speed": 20.0
}, { }, {
"frames": [{ "frames": [{
"duration": 1.0, "duration": 1.0,
@ -649,7 +649,7 @@ animations = [{
}], }],
"loop": false, "loop": false,
"name": &"hurt_up", "name": &"hurt_up",
"speed": 10.0 "speed": 20.0
}, { }, {
"frames": [{ "frames": [{
"duration": 1.0, "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 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(): func _ready():
MusicManager.play(preload("res://assets/music&sfx/music/ashveil-355633.mp3")) MusicManager.play(preload("res://assets/music&sfx/music/ashveil-355633.mp3"))
func _process(_delta: float) -> void:
# Called every frame. 'delta' is the elapsed time since the previous frame. var t = int(_spawn_control.elapsed_time)
func _process(delta: float) -> void: _timer_label.text = "%02d:%02d" % [t / 60, t % 60]
pass

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="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="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="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"] [sub_resource type="Resource" id="Resource_ssvqc"]
script = ExtResource("6_ir15t") script = ExtResource("6_ir15t")
@ -2383,11 +2384,6 @@ anchors_preset = 0
offset_right = 40.0 offset_right = 40.0
offset_bottom = 40.0 offset_bottom = 40.0
script = ExtResource("6_p57ef") 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")] [node name="Witch" parent="." unique_id=1188927311 instance=ExtResource("7_u5sy4")]
position = Vector2(304, 164) position = Vector2(304, 164)
@ -2409,24 +2405,88 @@ script = ExtResource("10_vtaks")
[node name="CanvasLayer" type="CanvasLayer" parent="." unique_id=1323249211] [node name="CanvasLayer" type="CanvasLayer" parent="." unique_id=1323249211]
[node name="ProgressBar" type="ProgressBar" parent="CanvasLayer" unique_id=825658619] [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 offset_bottom = 27.0
grow_horizontal = 2
max_value = 5.0 max_value = 5.0
step = 1.0 step = 1.0
show_percentage = false 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] [node name="LevelUpManager" type="Control" parent="CanvasLayer" unique_id=292400493]
process_mode = 3 process_mode = 3
layout_mode = 3 layout_mode = 3
anchors_preset = 0 anchors_preset = 5
offset_right = 40.0 anchor_left = 0.5
offset_bottom = 40.0 anchor_right = 0.5
grow_horizontal = 2
script = ExtResource("16_rysoc") 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] [node name="HBoxContainer" type="HBoxContainer" parent="CanvasLayer/LevelUpManager" unique_id=957625333]
layout_mode = 0 custom_minimum_size = Vector2(1000, 400)
offset_right = 40.0 layout_mode = 1
offset_bottom = 40.0 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] [node name="PerkEffects" type="Node2D" parent="." unique_id=2027136639]
script = ExtResource("16_ca42v") script = ExtResource("16_ca42v")
@ -2575,7 +2635,6 @@ theme_override_fonts/font = ExtResource("19_1kice")
theme_override_font_sizes/font_size = 32 theme_override_font_sizes/font_size = 32
text = "Back" 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/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/OptionsButton" to="PauseMenu" method="_on_options_button_pressed"]
[connection signal="pressed" from="PauseMenu/VBoxContainer/QuitButton" to="PauseMenu" method="_on_quit_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://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://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://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"] [sub_resource type="Resource" id="Resource_gstla"]
script = ExtResource("2_2npkn") script = ExtResource("2_2npkn")
@ -238,6 +239,86 @@ region = Rect2(256, 0, 64, 64)
atlas = ExtResource("3_rrqju") atlas = ExtResource("3_rrqju")
region = Rect2(320, 0, 64, 64) 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"] [sub_resource type="AtlasTexture" id="AtlasTexture_fur4c"]
atlas = ExtResource("4_wyhst") atlas = ExtResource("4_wyhst")
region = Rect2(0, 0, 64, 64) region = Rect2(0, 0, 64, 64)
@ -568,6 +649,86 @@ animations = [{
}, { }, {
"frames": [{ "frames": [{
"duration": 1.0, "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") "texture": SubResource("AtlasTexture_fur4c")
}, { }, {
"duration": 1.0, "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] [node name="AnimatedSprite2D" type="AnimatedSprite2D" parent="." unique_id=752118449]
texture_filter = 1 texture_filter = 1
sprite_frames = SubResource("SpriteFrames_cbi0b") sprite_frames = SubResource("SpriteFrames_cbi0b")
animation = &"walk_right" animation = &"hurt_up"
[node name="CollisionShape2D" type="CollisionShape2D" parent="." unique_id=769710804] [node name="CollisionShape2D" type="CollisionShape2D" parent="." unique_id=769710804]
position = Vector2(0, 1) 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")

View File

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

View File

@ -2,6 +2,7 @@ extends Area2D
class_name ProjectileBase class_name ProjectileBase
@export var size: float @export var size: float
@export var damage: int = 5
var speed = 200 var speed = 200
@export var element: String @export var element: String
var direction: Vector2 var direction: Vector2
@ -20,7 +21,7 @@ func launch(target: Vector2):
func _on_body_entered(body: Node2D) -> void: func _on_body_entered(body: Node2D) -> void:
if body.is_in_group("enemies"): if body.is_in_group("enemies"):
body.hit() body.take_damage(damage)
queue_free() queue_free()
func _remove(): 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 extends EnemyBase
func _ready() -> void: func _ready() -> void:
super() super()
speed = 0.1 speed = 15.0
hits_remaining = 2 max_hp = 25
hp = max_hp
$Area2D.body_entered.connect(_on_area_2d_body_entered) $Area2D.body_entered.connect(_on_area_2d_body_entered)
func _process(delta: float) -> void: func _process(delta: float) -> void:
super._process(delta)
if is_dying or is_hurt: if is_dying or is_hurt:
return return
_chase_witch() _chase_witch()
func _on_area_2d_body_entered(body: Node2D) -> void: func _on_area_2d_body_entered(body: Node2D) -> void:
if body == player: if body == player:
hit() take_damage(player.damage)

View File

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

View File

@ -1,11 +1,12 @@
extends Area2D extends Area2D
@export var damage: int = 15
# Called when the node enters the scene tree for the first time.
func _ready(): func _ready():
await get_tree().physics_frame
for body in get_overlapping_bodies(): for body in get_overlapping_bodies():
if body.is_in_group("enemies"): if body.is_in_group("enemies"):
body.hit() body.take_damage(damage)
await $AnimatedSprite2D.animation_finished await $AnimatedSprite2D.animation_finished
queue_free() 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: func _on_body_entered(body: Node2D) -> void:
if body.is_in_group("enemies"): if body.is_in_group("enemies"):
body.hit() body.take_damage(damage)
func _ready() -> void: func _ready() -> void:
damage = 6
if _is_spread_child: if _is_spread_child:
super() super()
return return

View File

@ -2,14 +2,19 @@ extends ProjectileBase
var fireball_aoe = false var fireball_aoe = false
var explosion_scene = preload("res://scenes/explosion.tscn") 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: func _on_body_entered(body: Node2D) -> void:
fireball_aoe = perk_effects.fireball_aoe_enabled fireball_aoe = perk_effects.fireball_aoe_enabled
if body.is_in_group("enemies"): if body.is_in_group("enemies"):
body.hit() body.take_damage(damage)
if fireball_aoe: if fireball_aoe:
var boom = explosion_scene.instantiate() var boom = explosion_scene.instantiate()
boom.global_position = global_position boom.global_position = global_position
get_parent().add_child(boom) get_parent().call_deferred("add_child", boom)
queue_free() queue_free()

View File

@ -2,7 +2,9 @@ extends Control
@onready var perk_effects = get_node("/root/Game/PerkEffects") @onready var perk_effects = get_node("/root/Game/PerkEffects")
var perks var perks
@onready var perkCard = preload("res://scenes/PerkCard.tscn")
# Called when the node enters the scene tree for the first time. # Called when the node enters the scene tree for the first time.
func _ready() -> void: func _ready() -> void:
perks = perk_effects.available_perks perks = perk_effects.available_perks
@ -17,18 +19,23 @@ func _process(delta: float) -> void:
func show_perks(): func show_perks():
if perks.is_empty(): if perks.is_empty():
return return
var tween = create_tween()
tween.tween_property($ColorRect, "color:a", 0.6, 0.3)
get_tree().paused = true get_tree().paused = true
var shuffled = perks.duplicate() var shuffled = perks.duplicate()
shuffled.shuffle() shuffled.shuffle()
var chosen = shuffled.slice(0, 3) var chosen = shuffled.slice(0, 3)
for x in chosen: for x in chosen:
var button = Button.new() var card = perkCard.instantiate()
button.text = x.name + "\n" + x.description $HBoxContainer.add_child(card)
button.pressed.connect(func(): select_perk(x)) card.setup(x, func(): select_perk(x))
$HBoxContainer.add_child(button)
func select_perk(perk): func select_perk(perk):
perk.effect.call() perk.effect.call()
get_tree().paused = false get_tree().paused = false
perks.erase(perk) perks.erase(perk)
for child in $HBoxContainer.get_children(): child.queue_free() 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,35 +3,62 @@ extends Node2D
@onready var witch = get_node("/root/Game/Witch") @onready var witch = get_node("/root/Game/Witch")
@onready var player = get_node("/root/Game/Player") @onready var player = get_node("/root/Game/Player")
var fireball = preload("res://scenes/fireball.tscn") var fireball = preload("res://scenes/fireball.tscn")
var throwing_knife = preload("res://scenes/throwing_knive.tscn")
var cauldron var cauldron
var available_perks: Array[Perk] = [] var available_perks: Array[Perk] = []
var fireball_aoe_enabled = false 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: func _ready() -> void:
cauldron = witch.get_node("CauldronBar") cauldron = witch.get_node("CauldronBar")
var dsh = Perk.new() var dsh = Perk.new()
dsh.name = "Doppelter Shuriken" dsh.name = "Double Shuriken"
dsh.description = "Wirft zwei Shurikens statt einem" dsh.description = "Throw two shurikens instead of one"
dsh.effect = double_shuriken dsh.effect = double_shuriken
available_perks.append(dsh) available_perks.append(dsh)
var faoe = Perk.new() var faoe = Perk.new()
faoe.name = "AOE-Fireball" faoe.name = "AOE Fireball"
faoe.description = "Feuerbälle erzeugen eine Explosion bei Berührung" faoe.description = "Fireballs spawn an explosion on contact"
faoe.effect = fireball_aoe faoe.effect = fireball_aoe
available_perks.append(faoe) available_perks.append(faoe)
var bexp = Perk.new() var bexp = Perk.new()
bexp.name = "Brewing-Explosion" bexp.name = "Brew Explosion"
bexp.description = "Die Hexe erzeugt eine Explosion am Ende des Brauens" bexp.description = "The Witch casts an explosion on finishing a brew"
bexp.effect = brew_explosion bexp.effect = brew_explosion
available_perks.append(bexp) 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)
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)
pass # Replace with function body.
# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta: float) -> void: 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(): func double_shuriken():
witch.shuriken_count = 2 witch.shuriken_count = 2
@ -42,3 +69,97 @@ func fireball_aoe():
func brew_explosion(): func brew_explosion():
cauldron.brew_explosion = true 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

@ -3,7 +3,8 @@ extends CharacterBody2D
var current_xp = 0 var current_xp = 0
var max_xp = 5 var max_xp = 5
var level = 1 var level = 1
var speed = 200 # speed in pixels/sec var speed = 200
var damage: int = 10
func _physics_process(delta): func _physics_process(delta):
var direction = Input.get_vector("ui_left", "ui_right", "ui_up", "ui_down") 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: func _ready() -> void:
speed = 500 speed = 500
super() super()
damage = 5
var first = get_nearest_enemy(global_position) var first = get_nearest_enemy(global_position)
if first == null: if first == null:
queue_free() queue_free()
@ -15,7 +16,7 @@ func _ready() -> void:
func _on_body_entered(body: Node2D) -> void: func _on_body_entered(body: Node2D) -> void:
if body.is_in_group("enemies") and not body.is_hurt and not body.is_dying: if body.is_in_group("enemies") and not body.is_hurt and not body.is_dying:
enemies_hit += 1 enemies_hit += 1
body.hit() body.take_damage(damage)
if enemies_hit == 20: if enemies_hit == 20:
queue_free() queue_free()
else: else:

View File

@ -1,22 +1,19 @@
extends EnemyBase 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: func _ready() -> void:
super() super()
speed = 0.1 speed = 15.0
max_hp = 10
hp = max_hp
func _process(delta: float) -> void: func _process(delta: float) -> void:
if is_dying: super._process(delta)
if is_dying or is_hurt:
return return
_chase_witch() _chase_witch()
pass
func _on_area_2d_body_entered(body: Node2D) -> void: func _on_area_2d_body_entered(body: Node2D) -> void:
if is_dying: if is_dying:
return return
if body == player: if body == player:
die() take_damage(player.damage)
pass # Replace with function body.

View File

@ -1,72 +1,117 @@
extends Control extends Control
var up_left var up_left: Vector2
var down_right var down_right: Vector2
var up_right var up_right: Vector2
var down_left var down_left: Vector2
var viewport_rect var elapsed_time: float = 0.0
var elapsed_time = 0.0
@export var spawn_entries: Array[SpawnEntry] 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: func _ready() -> void:
var camera: Camera2D = get_parent().get_node("Camera2D") var camera: Camera2D = get_parent().get_node("Camera2D")
var viewport_size = get_viewport_rect().size var viewport_size = get_viewport_rect().size
var world_size = viewport_size / camera.zoom 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 up_left = world_origin
down_right = world_origin + world_size down_right = world_origin + world_size
up_right = Vector2(down_right.x, up_left.y) up_right = Vector2(down_right.x, up_left.y)
down_left = Vector2(up_left.x, down_right.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: func get_spawn_position() -> Vector2:
var side = randi() % 4 var side = randi() % 4
var spawn_x var spawn_x: float
var spawn_y var spawn_y: float
if side == 0: if side == 0:
# oben
spawn_x = randf_range(up_left.x, up_right.x) spawn_x = randf_range(up_left.x, up_right.x)
spawn_y = up_left.y spawn_y = up_left.y
elif side == 1: elif side == 1:
# rechts
spawn_x = up_right.x spawn_x = up_right.x
spawn_y = randf_range(up_right.y, down_right.y) spawn_y = randf_range(up_right.y, down_right.y)
elif side == 2: elif side == 2:
#unten
spawn_x = randf_range(up_left.x, up_right.x) spawn_x = randf_range(up_left.x, up_right.x)
spawn_y = down_left.y spawn_y = down_left.y
elif side == 3: else:
#links
spawn_x = up_left.x spawn_x = up_left.x
spawn_y = randf_range(up_right.y, down_right.y) spawn_y = randf_range(up_right.y, down_right.y)
return Vector2(spawn_x, spawn_y) return Vector2(spawn_x, spawn_y)
# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta: float) -> void: func _process(delta: float) -> void:
elapsed_time += delta elapsed_time += delta
pass
func spawn_enemy() -> void: for si in stages.size():
var sum_weight = 0.0 var stage: SpawnStage = stages[si]
var available = [] if elapsed_time < stage.time_start:
for entry in spawn_entries: continue
if entry.min_time <= elapsed_time: if stage.time_end != -1.0 and elapsed_time > stage.time_end:
available.append(entry) continue
sum_weight += entry.weight
var roll = randf() * sum_weight var t: float
var winner = null if stage.time_end == -1.0:
for entry in available: t = 1.0
roll -= entry.weight else:
if roll <= 0: t = clamp(
winner = entry (elapsed_time - stage.time_start) / (stage.time_end - stage.time_start),
break 0.0, 1.0
if winner == null: )
return
var enemy = winner.enemy.instantiate() 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() enemy.global_position = get_spawn_position()
state["alive"] += 1
state["spawned_total"] += 1
enemy.tree_exited.connect(func(): state["alive"] -= 1)
add_child(enemy) 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

View File

@ -1,5 +1,7 @@
extends CharacterBody2D extends CharacterBody2D
signal health_changed(current_hp: int, max_hp: int)
var camera var camera
var is_casting = false var is_casting = false
var fireball = preload("res://scenes/fireball.tscn") var fireball = preload("res://scenes/fireball.tscn")
@ -7,9 +9,33 @@ var shuriken = preload("res://scenes/shuriken.tscn")
var fire_swirl = preload("res://scenes/fire_swirl.tscn") var fire_swirl = preload("res://scenes/fire_swirl.tscn")
var shuriken_count = 1 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: func _ready() -> void:
$CauldronBar.witch = self $CauldronBar.witch = self
camera = get_node("/root/Game/Camera2D") 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: func _physics_process(delta: float) -> void:
# Add the gravity. # Add the gravity.
@ -43,10 +69,26 @@ func shoot_shuriken():
get_parent().add_child(sh) get_parent().add_child(sh)
await get_tree().create_timer(0.2).timeout await get_tree().create_timer(0.2).timeout
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 nearest = null
var min_distance = INF var min_distance = INF
for enemy in get_tree().get_nodes_in_group("enemies"): 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) var dist = from.distance_to(enemy.global_position)
if dist < min_distance: if dist < min_distance:
min_distance = dist min_distance = dist