Added Laser Spell, no recipe yet
parent
24d45d1e9c
commit
89446660c0
|
|
@ -0,0 +1,122 @@
|
|||
[gd_scene format=3 uid="uid://d2mpjsuueg0bn"]
|
||||
|
||||
[ext_resource type="Script" uid="uid://bdhx27edemfce" path="res://scripts/beam.gd" id="1_beam00"]
|
||||
[ext_resource type="Texture2D" uid="uid://dxox0vjihmukh" path="res://assets/Fire Pixel Bullet 16x16/All_Fire_Bullet_Pixel_16x16_05.png" id="2_hl8vi"]
|
||||
|
||||
[sub_resource type="AtlasTexture" id="AtlasTexture_daiji"]
|
||||
atlas = ExtResource("2_hl8vi")
|
||||
region = Rect2(96, 0, 16, 16)
|
||||
|
||||
[sub_resource type="AtlasTexture" id="AtlasTexture_bawts"]
|
||||
atlas = ExtResource("2_hl8vi")
|
||||
region = Rect2(112, 0, 16, 16)
|
||||
|
||||
[sub_resource type="AtlasTexture" id="AtlasTexture_8wlve"]
|
||||
atlas = ExtResource("2_hl8vi")
|
||||
region = Rect2(128, 0, 16, 16)
|
||||
|
||||
[sub_resource type="AtlasTexture" id="AtlasTexture_bt3ye"]
|
||||
atlas = ExtResource("2_hl8vi")
|
||||
region = Rect2(144, 0, 16, 16)
|
||||
|
||||
[sub_resource type="AtlasTexture" id="AtlasTexture_a06w7"]
|
||||
atlas = ExtResource("2_hl8vi")
|
||||
region = Rect2(96, 16, 16, 16)
|
||||
|
||||
[sub_resource type="AtlasTexture" id="AtlasTexture_5fvdj"]
|
||||
atlas = ExtResource("2_hl8vi")
|
||||
region = Rect2(112, 16, 16, 16)
|
||||
|
||||
[sub_resource type="AtlasTexture" id="AtlasTexture_djxf5"]
|
||||
atlas = ExtResource("2_hl8vi")
|
||||
region = Rect2(128, 16, 16, 16)
|
||||
|
||||
[sub_resource type="AtlasTexture" id="AtlasTexture_eeead"]
|
||||
atlas = ExtResource("2_hl8vi")
|
||||
region = Rect2(144, 16, 16, 16)
|
||||
|
||||
[sub_resource type="AtlasTexture" id="AtlasTexture_qfoqh"]
|
||||
atlas = ExtResource("2_hl8vi")
|
||||
region = Rect2(96, 32, 16, 16)
|
||||
|
||||
[sub_resource type="AtlasTexture" id="AtlasTexture_tuykp"]
|
||||
atlas = ExtResource("2_hl8vi")
|
||||
region = Rect2(112, 32, 16, 16)
|
||||
|
||||
[sub_resource type="AtlasTexture" id="AtlasTexture_2dcgn"]
|
||||
atlas = ExtResource("2_hl8vi")
|
||||
region = Rect2(128, 32, 16, 16)
|
||||
|
||||
[sub_resource type="AtlasTexture" id="AtlasTexture_7703o"]
|
||||
atlas = ExtResource("2_hl8vi")
|
||||
region = Rect2(144, 32, 16, 16)
|
||||
|
||||
[sub_resource type="SpriteFrames" id="SpriteFrames_beam0"]
|
||||
animations = [{
|
||||
"frames": [{
|
||||
"duration": 1.0,
|
||||
"texture": SubResource("AtlasTexture_daiji")
|
||||
}, {
|
||||
"duration": 1.0,
|
||||
"texture": SubResource("AtlasTexture_bawts")
|
||||
}, {
|
||||
"duration": 1.0,
|
||||
"texture": SubResource("AtlasTexture_8wlve")
|
||||
}, {
|
||||
"duration": 1.0,
|
||||
"texture": SubResource("AtlasTexture_bt3ye")
|
||||
}],
|
||||
"loop": true,
|
||||
"name": &"end",
|
||||
"speed": 10.0
|
||||
}, {
|
||||
"frames": [{
|
||||
"duration": 1.0,
|
||||
"texture": SubResource("AtlasTexture_a06w7")
|
||||
}, {
|
||||
"duration": 1.0,
|
||||
"texture": SubResource("AtlasTexture_5fvdj")
|
||||
}, {
|
||||
"duration": 1.0,
|
||||
"texture": SubResource("AtlasTexture_djxf5")
|
||||
}, {
|
||||
"duration": 1.0,
|
||||
"texture": SubResource("AtlasTexture_eeead")
|
||||
}],
|
||||
"loop": true,
|
||||
"name": &"middle",
|
||||
"speed": 10.0
|
||||
}, {
|
||||
"frames": [{
|
||||
"duration": 1.0,
|
||||
"texture": SubResource("AtlasTexture_qfoqh")
|
||||
}, {
|
||||
"duration": 1.0,
|
||||
"texture": SubResource("AtlasTexture_tuykp")
|
||||
}, {
|
||||
"duration": 1.0,
|
||||
"texture": SubResource("AtlasTexture_2dcgn")
|
||||
}, {
|
||||
"duration": 1.0,
|
||||
"texture": SubResource("AtlasTexture_7703o")
|
||||
}],
|
||||
"loop": true,
|
||||
"name": &"start",
|
||||
"speed": 10.0
|
||||
}]
|
||||
|
||||
[sub_resource type="RectangleShape2D" id="RectangleShape2D_beam0"]
|
||||
size = Vector2(16, 8)
|
||||
|
||||
[node name="Beam" type="Area2D" unique_id=968931754]
|
||||
script = ExtResource("1_beam00")
|
||||
|
||||
[node name="AnimatedSprite2D" type="AnimatedSprite2D" parent="." unique_id=100000001]
|
||||
texture_filter = 1
|
||||
sprite_frames = SubResource("SpriteFrames_beam0")
|
||||
animation = &"end"
|
||||
frame_progress = 0.02647079
|
||||
|
||||
[node name="CollisionShape2D" type="CollisionShape2D" parent="." unique_id=100000002]
|
||||
shape = SubResource("RectangleShape2D_beam0")
|
||||
disabled = true
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
[gd_scene format=3 uid="uid://claser0spell1"]
|
||||
|
||||
[ext_resource type="Script" path="res://scripts/laser.gd" id="1_laser0"]
|
||||
|
||||
[node name="Laser" type="Node2D"]
|
||||
script = ExtResource("1_laser0")
|
||||
|
|
@ -8,6 +8,7 @@ const SHURIKEN = "SHURIKEN"
|
|||
const FIREBALL = "FIREBALL"
|
||||
const FIRE_SWIRL = "FIRE_SWIRL"
|
||||
const TORNADO = "TORNADO"
|
||||
const LASER = "LASER"
|
||||
|
||||
# Each spell's display recipe: sorted apples-first, grapes-last
|
||||
var recipes: Dictionary = {
|
||||
|
|
@ -15,6 +16,7 @@ var recipes: Dictionary = {
|
|||
FIREBALL: [APPLE, APPLE, APPLE],
|
||||
FIRE_SWIRL: [APPLE, APPLE, GRAPE],
|
||||
TORNADO: [GRAPE, GRAPE, GRAPE],
|
||||
LASER: [],
|
||||
}
|
||||
|
||||
# Takes cauldron slot_states (uses texture indices: 2 = apple, 4 = grape)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,11 @@
|
|||
extends Area2D
|
||||
|
||||
@export var beam_type := "middle"
|
||||
|
||||
@onready var sprite: AnimatedSprite2D = $AnimatedSprite2D
|
||||
@onready var shape: CollisionShape2D = $CollisionShape2D
|
||||
|
||||
func _ready() -> void:
|
||||
if sprite.sprite_frames.has_animation(beam_type):
|
||||
sprite.play(beam_type)
|
||||
shape.disabled = beam_type != "middle"
|
||||
|
|
@ -0,0 +1 @@
|
|||
uid://bdhx27edemfce
|
||||
|
|
@ -14,6 +14,7 @@ func _ready() -> void:
|
|||
SpellLibrary.SHURIKEN: _witch.shoot_shuriken,
|
||||
SpellLibrary.FIRE_SWIRL: _witch.shoot_fire_swirl,
|
||||
SpellLibrary.TORNADO: _witch.shoot_tornado,
|
||||
SpellLibrary.LASER: _witch.shoot_laser,
|
||||
}
|
||||
_build_ui()
|
||||
hide()
|
||||
|
|
|
|||
|
|
@ -0,0 +1,91 @@
|
|||
extends Node2D
|
||||
|
||||
const BEAM_DURATION := 3.0
|
||||
const PRIMARY_TICK_DMG := 15
|
||||
const SPLASH_TICK_DMG := 3
|
||||
const TICK_INTERVAL := 0.5
|
||||
|
||||
@export var segment_size := 16.0
|
||||
|
||||
var beam_seg := preload("res://scenes/beam.tscn")
|
||||
var target: Node2D = null
|
||||
var all_segs: Array = []
|
||||
var mid_segs: Array = []
|
||||
var tick_timer := 0.0
|
||||
var elapsed := 0.0
|
||||
var done := false
|
||||
|
||||
func _ready() -> void:
|
||||
target = get_highest_hp_enemy()
|
||||
if target == null:
|
||||
queue_free()
|
||||
return
|
||||
spawn_beam()
|
||||
|
||||
func _process(delta: float) -> void:
|
||||
if done:
|
||||
return
|
||||
elapsed += delta
|
||||
tick_timer += delta
|
||||
if tick_timer >= TICK_INTERVAL:
|
||||
tick_timer -= TICK_INTERVAL
|
||||
do_damage_tick()
|
||||
if elapsed >= BEAM_DURATION:
|
||||
done = true
|
||||
cleanup()
|
||||
|
||||
func spawn_beam() -> void:
|
||||
var origin := global_position
|
||||
var dest := target.global_position
|
||||
var dir := origin.direction_to(dest)
|
||||
var dist := origin.distance_to(dest)
|
||||
var angle := dir.angle()
|
||||
|
||||
place_seg("start", origin, angle)
|
||||
|
||||
var n_mid := int(max(0.0, dist - segment_size * 2.0) / segment_size)
|
||||
for i in range(n_mid):
|
||||
var pos := origin + dir * (segment_size * (float(i) + 1.0))
|
||||
mid_segs.append(place_seg("middle", pos, angle))
|
||||
|
||||
place_seg("end", dest, angle)
|
||||
|
||||
func place_seg(type: String, pos: Vector2, angle: float) -> Node:
|
||||
var seg = beam_seg.instantiate()
|
||||
seg.beam_type = type
|
||||
seg.global_position = pos
|
||||
seg.rotation = angle
|
||||
get_parent().add_child(seg)
|
||||
all_segs.append(seg)
|
||||
return seg
|
||||
|
||||
func do_damage_tick() -> void:
|
||||
if is_instance_valid(target) and not target.is_dying:
|
||||
target.take_damage(PRIMARY_TICK_DMG)
|
||||
|
||||
var hit: Array = []
|
||||
for seg in mid_segs:
|
||||
if not is_instance_valid(seg):
|
||||
continue
|
||||
for body in seg.get_overlapping_bodies():
|
||||
if body.is_in_group("enemies") and not body.is_dying \
|
||||
and body != target and not hit.has(body):
|
||||
body.take_damage(SPLASH_TICK_DMG)
|
||||
hit.append(body)
|
||||
|
||||
func cleanup() -> void:
|
||||
for seg in all_segs:
|
||||
if is_instance_valid(seg):
|
||||
seg.queue_free()
|
||||
queue_free()
|
||||
|
||||
func get_highest_hp_enemy() -> Node:
|
||||
var best: Node = null
|
||||
var best_hp: int = -1
|
||||
for enemy in get_tree().get_nodes_in_group("enemies"):
|
||||
if not is_instance_valid(enemy) or enemy.is_dying:
|
||||
continue
|
||||
if enemy.hp > best_hp:
|
||||
best_hp = enemy.hp
|
||||
best = enemy
|
||||
return best
|
||||
|
|
@ -0,0 +1 @@
|
|||
uid://dp6b3imslv10d
|
||||
|
|
@ -8,6 +8,7 @@ var fireball = preload("res://scenes/fireball.tscn")
|
|||
var shuriken = preload("res://scenes/shuriken.tscn")
|
||||
var fire_swirl = preload("res://scenes/fire_swirl.tscn")
|
||||
var tornado = preload("res://scenes/tornado.tscn")
|
||||
var laser = preload("res://scenes/laser.tscn")
|
||||
var shuriken_count = 1
|
||||
var _fire_sfx = preload("res://assets/music&sfx/sfx/fire.wav")
|
||||
|
||||
|
|
@ -100,6 +101,12 @@ func shoot_tornado():
|
|||
get_parent().add_child(tw)
|
||||
camera.shake(0.3, 0.8)
|
||||
|
||||
func shoot_laser():
|
||||
var ls = laser.instantiate()
|
||||
ls.global_position = global_position
|
||||
get_parent().add_child(ls)
|
||||
camera.shake(0.4, 1.2)
|
||||
|
||||
func take_damage(amount: int) -> void:
|
||||
if is_invincible:
|
||||
return
|
||||
|
|
|
|||
Loading…
Reference in New Issue