feat/tornado (#13)

Co-authored-by: Jaro <jaro@MacBook.local>
Co-authored-by: 3002102 <3002102@stud.th-mannheim.de>
Reviewed-on: #13
pull/14/head
Jaro Winkelhausen 2026-04-24 01:56:22 +02:00
parent c959b0d3e5
commit c7e1afdc37
10 changed files with 218 additions and 6 deletions

BIN
.DS_Store vendored

Binary file not shown.

3
.gitignore vendored
View File

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

BIN
assets/.DS_Store vendored

Binary file not shown.

Binary file not shown.

Binary file not shown.

152
scenes/tornado.tscn 100644
View File

@ -0,0 +1,152 @@
[gd_scene format=3 uid="uid://byqfrmwg0mi3y"]
[ext_resource type="Script" 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 = 39.051247
[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

@ -82,15 +82,16 @@ func progres_bar(fruit):
func brew(fruits): func brew(fruits):
is_brewing = true is_brewing = true
var unique = get_unique_fruits()
await ignite_cauldrons() 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() witch.shoot_fire_swirl()
elif unique.has(2) and unique.size() == 1: elif apple_count == 3:
witch.shoot_fireballs() witch.shoot_fireballs()
elif unique.has(4) and unique.size() == 1: elif grape_count == 3:
witch.shoot_shuriken() witch.shoot_tornado()
elif unique.has(2) and unique.has(4) and unique.size() == 2: elif apple_count == 1 and grape_count == 2:
witch.shoot_fireballs() witch.shoot_fireballs()
witch.shoot_shuriken() witch.shoot_shuriken()
reset_texture() reset_texture()

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

@ -7,6 +7,7 @@ var is_casting = false
var fireball = preload("res://scenes/fireball.tscn") var fireball = preload("res://scenes/fireball.tscn")
var shuriken = preload("res://scenes/shuriken.tscn") 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 tornado = preload("res://scenes/tornado.tscn")
var shuriken_count = 1 var shuriken_count = 1
var max_hp: int = 100 var max_hp: int = 100
@ -68,6 +69,13 @@ func shoot_shuriken():
sh.global_position = global_position sh.global_position = global_position
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 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 take_damage(amount: int) -> void: func take_damage(amount: int) -> void:
if is_invincible: if is_invincible: