From 294f87adb4441ec25316601505ca1a7e97fa24c7 Mon Sep 17 00:00:00 2001 From: Daniel Weipert Date: Fri, 19 Jul 2024 14:24:09 +0200 Subject: update --- Scenes/Entities/Enemies/Balloon.gd | 6 +- Scenes/Entities/Enemies/Balloon.tscn | 2 +- Scenes/Entities/Enemies/Components/Health.gd | 37 +++- Scenes/Entities/Enemies/Components/Movement.gd | 281 +++++++++++++++++-------- Scenes/Entities/Enemies/Flower.gd | 5 + Scenes/Entities/Enemies/Flowers.gd | 5 +- Scenes/Entities/Enemies/Slime.gd | 8 +- Scenes/Entities/Enemies/Slime.tscn | 17 +- Scenes/Entities/Enemies/Snake.gd | 15 +- Scenes/Entities/Enemies/Snake.tscn | 1 + Scenes/Entities/Enemies/Tree.gd | 16 +- Scenes/Entities/Enemies/Tree.tscn | 7 +- 12 files changed, 273 insertions(+), 127 deletions(-) (limited to 'Scenes/Entities/Enemies') diff --git a/Scenes/Entities/Enemies/Balloon.gd b/Scenes/Entities/Enemies/Balloon.gd index ec41822..179dda7 100644 --- a/Scenes/Entities/Enemies/Balloon.gd +++ b/Scenes/Entities/Enemies/Balloon.gd @@ -7,9 +7,11 @@ func _ready(): add_to_group("enemies") component_collision.init() + component_movement.init() -func _physics_process(delta): - component_movement.physics_process(delta) +#func _physics_process(delta): + #pass + #component_movement.physics_process(delta) # todo: animation shadow diff --git a/Scenes/Entities/Enemies/Balloon.tscn b/Scenes/Entities/Enemies/Balloon.tscn index c1b0701..4100d54 100644 --- a/Scenes/Entities/Enemies/Balloon.tscn +++ b/Scenes/Entities/Enemies/Balloon.tscn @@ -144,7 +144,7 @@ shape = SubResource("CapsuleShape2D_abul4") [node name="Movement" parent="." instance=ExtResource("15_fwetl")] entityPath = NodePath("..") spritePath = NodePath("../AnimatedSprite2D") -SPEED = 10.0 +SPEED = 0.7 timer_time = 10.0 [node name="Collision" parent="." instance=ExtResource("16_yau34")] diff --git a/Scenes/Entities/Enemies/Components/Health.gd b/Scenes/Entities/Enemies/Components/Health.gd index 2bd2447..00bf9e0 100644 --- a/Scenes/Entities/Enemies/Components/Health.gd +++ b/Scenes/Entities/Enemies/Components/Health.gd @@ -2,6 +2,7 @@ class_name ComponentHealth extends Node +signal hit signal died @export_node_path("CharacterBody2D") var entityPath: NodePath @@ -21,7 +22,8 @@ var drop_items = [ preload("res://Scenes/Entities/Objects/Coin.tscn"), ] -var is_dying = false +@export var invincibility_timeout: float = 1.0 +var is_invincible = false func _ready(): @@ -30,23 +32,38 @@ func _ready(): func take_damage(): + if is_invincible: + return + + emit_signal("hit") + health -= 1 - if health <= 0 and not is_dying: + is_invincible = true + if component_movement: # stop all movement + component_movement.pause() + + sprite.play("death") + await sprite.animation_finished + + if health <= 0: death() + else: + if component_movement: # resume all movement + component_movement.unpause() + + #var flicker_speed = 0.2 + #var tween = create_tween().set_loops(invincibility_timeout / (flicker_speed*2)) + #tween.tween_property(sprite, "modulate", Color(1, 1, 1, 0.5), flicker_speed) + #tween.tween_property(sprite, "modulate", Color(1, 1, 1, 1), flicker_speed) + # + #await get_tree().create_timer(invincibility_timeout).timeout + is_invincible = false func death(): - is_dying = true emit_signal("died") - if component_movement: # stop all movement - component_movement.process_mode = Node.PROCESS_MODE_DISABLED - entity.set_physics_process(false) - - sprite.play("death") - await sprite.animation_finished - assert(sprite.sprite_frames.has_animation("death_post")) sprite.play("death_post") diff --git a/Scenes/Entities/Enemies/Components/Movement.gd b/Scenes/Entities/Enemies/Components/Movement.gd index 3174508..98fb43a 100644 --- a/Scenes/Entities/Enemies/Components/Movement.gd +++ b/Scenes/Entities/Enemies/Components/Movement.gd @@ -10,11 +10,14 @@ signal direction_changed @export_node_path("AnimatedSprite2D") var spritePath: NodePath @onready var sprite: AnimatedSprite2D = get_node(spritePath) -@export var SPEED: float +@export_node_path("ComponentCollision") var component_collision_path: NodePath +var component_collision: ComponentCollision + +@export_range(0, 2, 0.01) var SPEED: float const DIRECTIONS = [Vector2.UP, Vector2.RIGHT, Vector2.DOWN, Vector2.LEFT] var CURRENT_DIRECTION = Vector2.UP -var LAST_DIRECTION = Vector2.UP +var FIXED_DIRECTION = null var was_colliding = false var animations: Dictionary = { @@ -24,6 +27,11 @@ var animations: Dictionary = { "left": "left", "right": "right", } +var CURRENT_ANIMATION = { + "name": "default", + "frame": 0, + "progress": 0, +} @export var timer_time: float = 3.0 @onready var MovementTimer: Timer = Timer.new() @@ -31,101 +39,183 @@ var animations: Dictionary = { @export var follows: bool = false @export_range(1, 100, 1) var follow_chance: int = 100 +var is_paused = false -func _ready(): - MovementTimer.wait_time = timer_time - MovementTimer.autostart = true - MovementTimer.connect("timeout", Callable(_on_movement_timer_timeout)) - add_child(MovementTimer) +var tween: Tween -func physics_process(delta): - if CURRENT_DIRECTION == Vector2.UP: - entity.velocity.y -= SPEED/2 - if sprite.sprite_frames.has_animation(animations["up"]): - sprite.play(animations["up"]) - elif CURRENT_DIRECTION == Vector2.DOWN: - entity.velocity.y += SPEED/2 - if sprite.sprite_frames.has_animation(animations["down"]): - sprite.play(animations["down"]) - elif CURRENT_DIRECTION == Vector2.LEFT: - entity.velocity.x -= SPEED/2 - if sprite.sprite_frames.has_animation(animations["left"]): - sprite.play(animations["left"]) - elif CURRENT_DIRECTION == Vector2.RIGHT: - entity.velocity.x += SPEED/2 - if sprite.sprite_frames.has_animation(animations["right"]): - sprite.play(animations["right"]) - - if sprite.sprite_frames.has_animation(animations["default"]): - sprite.play(animations["default"]) - - var collision = entity.move_and_collide(entity.velocity * delta) - entity.velocity = entity.velocity.lerp(Vector2(0, 0), 1) # speed too low => no collision - - # todo movement along grid (maybe move position to current tile center) - var target_grid_position = Utilities.from_grid_to_position(Utilities.get_level_position(entity) + CURRENT_DIRECTION) - entity.position = entity.position.move_toward(target_grid_position, delta*SPEED/2) - # todo or set velocity to tiles per SPEED per second somehow, instead of Timer - - if collision: - was_colliding = true - if MovementTimer.time_left > 0: - _on_movement_timer_timeout() - else: - was_colliding = false +func _ready(): + #MovementTimer.wait_time = timer_time + #MovementTimer.autostart = true + #MovementTimer.connect("timeout", Callable(_on_movement_timer_timeout)) + #add_child(MovementTimer) + pass + +func init(): + #if component_collision_path: + #component_collision = get_node(component_collision_path) + #component_collision.collision_area.connect("collided", func(body): + #if check_direction_has_intersection(CURRENT_DIRECTION): + #tween.stop() + #move() + #) + ## TODO: area mit direction change detection? on solid and bomb? - return collision + await get_tree().create_timer(0.2).timeout # wait for surrounding collision objects to load + move() + + +#func physics_process(delta): + #if is_paused: + #return null + # + #if CURRENT_DIRECTION == Vector2.UP: + #entity.velocity.y -= SPEED/2 + #if sprite.sprite_frames.has_animation(animations["up"]): + #sprite.play(animations["up"]) + #elif CURRENT_DIRECTION == Vector2.DOWN: + #entity.velocity.y += SPEED/2 + #if sprite.sprite_frames.has_animation(animations["down"]): + #sprite.play(animations["down"]) + #elif CURRENT_DIRECTION == Vector2.LEFT: + #entity.velocity.x -= SPEED/2 + #if sprite.sprite_frames.has_animation(animations["left"]): + #sprite.play(animations["left"]) + #elif CURRENT_DIRECTION == Vector2.RIGHT: + #entity.velocity.x += SPEED/2 + #if sprite.sprite_frames.has_animation(animations["right"]): + #sprite.play(animations["right"]) + # + #if sprite.sprite_frames.has_animation(animations["default"]): + #sprite.play(animations["default"]) + # + #var collision = entity.move_and_collide(entity.velocity * delta) + #entity.velocity = entity.velocity.lerp(Vector2(0, 0), 1) # speed too low => no collision + # + ## todo movement along grid (maybe move position to current tile center) + #var target_grid_position = Utilities.from_grid_to_position(Utilities.get_level_position(entity) + CURRENT_DIRECTION) + #entity.position = entity.position.move_toward(target_grid_position, delta*SPEED/2) + ## todo or set velocity to tiles per SPEED per second somehow, instead of Timer + ## use raycast in every direction to check next valid tile, move there + ## get start, current and end position, check if reached instead of velocity to tiles per second or Timer + # + #if collision: + #was_colliding = true + #if MovementTimer.time_left > 0: + #_on_movement_timer_timeout() + #else: + #was_colliding = false + # + #return collision func set_animations(new_animations: Dictionary): animations.merge(new_animations, true) -func _on_movement_timer_timeout(): - var randomize_direction = false +#func _on_movement_timer_timeout(): + #var randomize_direction = false +# + #if false and follows and randi_range(0, 100) <= follow_chance: + #var player_direction = entity.position.direction_to(Global.player.position) + #var query = PhysicsRayQueryParameters2D.new() + #query.set_from(entity.position) + #query.set_to(Global.player.position) + #query.set_collision_mask(entity.collision_mask) + #var intersection = entity.get_world_2d().direct_space_state.intersect_ray(query) + #if intersection: + #randomize_direction = true + # + #if abs(player_direction.x) >= abs(player_direction.y): + #if player_direction.x >= 0: + #CURRENT_DIRECTION = Vector2.RIGHT + #elif player_direction.x < 0: + #CURRENT_DIRECTION = Vector2.LEFT + #elif abs(player_direction.y) > abs(player_direction.x): + #if player_direction.y >= 0: + #CURRENT_DIRECTION = Vector2.DOWN + #elif player_direction.y < 0: + #CURRENT_DIRECTION = Vector2.UP + # + #if was_colliding and LAST_DIRECTION == CURRENT_DIRECTION: + #randomize_direction = true + #else: + #randomize_direction = true + # + #if randomize_direction: + #var directions = DIRECTIONS.duplicate() + # + #directions.erase(CURRENT_DIRECTION) + #directions.shuffle() + # + #if not directions.is_empty(): + #CURRENT_DIRECTION = directions[0] +# + #emit_signal("direction_changed", CURRENT_DIRECTION) + #LAST_DIRECTION = CURRENT_DIRECTION + # + #if not sprite.sprite_frames.has_animation(animations["default"]): + #var frame = sprite.frame + #var progress = sprite.frame_progress + #if CURRENT_DIRECTION == Vector2.UP and sprite.sprite_frames.has_animation(animations["up"]): + #sprite.play(animations["up"]) + #elif CURRENT_DIRECTION == Vector2.DOWN and sprite.sprite_frames.has_animation(animations["down"]): + #sprite.play(animations["down"]) + #elif CURRENT_DIRECTION == Vector2.LEFT and sprite.sprite_frames.has_animation(animations["left"]): + #sprite.play(animations["left"]) + #elif CURRENT_DIRECTION == Vector2.RIGHT and sprite.sprite_frames.has_animation(animations["right"]): + #sprite.play(animations["right"]) + #sprite.set_frame_and_progress(frame, progress) + # + #MovementTimer.start() + + +func pause(): + is_paused = true + #MovementTimer.paused = true + + process_mode = Node.PROCESS_MODE_DISABLED - if false and follows and randi_range(0, 100) <= follow_chance: - var player_direction = entity.position.direction_to(Global.player.position) - var query = PhysicsRayQueryParameters2D.new() - query.set_from(entity.position) - query.set_to(Global.player.position) - query.set_collision_mask(entity.collision_mask) - var intersection = entity.get_world_2d().direct_space_state.intersect_ray(query) - if intersection: - randomize_direction = true - - if abs(player_direction.x) >= abs(player_direction.y): - if player_direction.x >= 0: - CURRENT_DIRECTION = Vector2.RIGHT - elif player_direction.x < 0: - CURRENT_DIRECTION = Vector2.LEFT - elif abs(player_direction.y) > abs(player_direction.x): - if player_direction.y >= 0: - CURRENT_DIRECTION = Vector2.DOWN - elif player_direction.y < 0: - CURRENT_DIRECTION = Vector2.UP - - if was_colliding and LAST_DIRECTION == CURRENT_DIRECTION: - randomize_direction = true - else: +func unpause(): + is_paused = false + #MovementTimer.paused = false + + process_mode = Node.PROCESS_MODE_INHERIT + sprite.play(CURRENT_ANIMATION.name) + sprite.set_frame_and_progress(CURRENT_ANIMATION.frame, CURRENT_ANIMATION.progress) + + +func move(): + var can_move = true + var randomize_direction = false + + #randomize_direction = randi() % 10 > 8 + if check_direction_has_intersection(CURRENT_DIRECTION): randomize_direction = true - + + var directions = DIRECTIONS.duplicate() if randomize_direction: - var directions = DIRECTIONS.duplicate() - directions.erase(CURRENT_DIRECTION) - directions.shuffle() - - if not directions.is_empty(): - CURRENT_DIRECTION = directions[0] - + directions.shuffle() + + for idx in range(directions.size()): + if not check_direction_has_intersection(directions[idx]): + CURRENT_DIRECTION = directions[idx] + break + if idx == directions.size() - 1: + can_move = false + + if FIXED_DIRECTION: + CURRENT_DIRECTION = FIXED_DIRECTION + emit_signal("direction_changed", CURRENT_DIRECTION) - LAST_DIRECTION = CURRENT_DIRECTION - if not sprite.sprite_frames.has_animation(animations["default"]): - var frame = sprite.frame - var progress = sprite.frame_progress + var frame = sprite.frame + var progress = sprite.frame_progress + var animation = sprite.animation + if sprite.sprite_frames.has_animation(animations["default"]): + sprite.play(animations["default"]) + else: if CURRENT_DIRECTION == Vector2.UP and sprite.sprite_frames.has_animation(animations["up"]): sprite.play(animations["up"]) elif CURRENT_DIRECTION == Vector2.DOWN and sprite.sprite_frames.has_animation(animations["down"]): @@ -134,6 +224,31 @@ func _on_movement_timer_timeout(): sprite.play(animations["left"]) elif CURRENT_DIRECTION == Vector2.RIGHT and sprite.sprite_frames.has_animation(animations["right"]): sprite.play(animations["right"]) - sprite.set_frame_and_progress(frame, progress) + sprite.set_frame_and_progress(frame, progress) + + CURRENT_ANIMATION.name = animation + CURRENT_ANIMATION.frame = frame + CURRENT_ANIMATION.progress = progress + + var target_grid_position = Utilities.from_grid_to_position(Utilities.get_level_position(entity) + CURRENT_DIRECTION) + + tween = create_tween() + if can_move: + tween.tween_property(entity, "position", target_grid_position, 1/SPEED).set_ease(Tween.EASE_IN_OUT) + else: + tween.tween_callback(func(): + await get_tree().create_timer(1/SPEED).timeout + ) + tween.tween_callback(func(): + move() + ) + + +func check_direction_has_intersection(direction: Vector2): + var query = PhysicsRayQueryParameters2D.new() + query.set_from(entity.position) + query.set_to(Utilities.from_grid_to_position(Utilities.get_level_position(entity) + direction)) + query.set_collision_mask(entity.collision_mask) + var intersection = entity.get_world_2d().direct_space_state.intersect_ray(query) - MovementTimer.start() + return intersection diff --git a/Scenes/Entities/Enemies/Flower.gd b/Scenes/Entities/Enemies/Flower.gd index 3e50e80..d287bdc 100644 --- a/Scenes/Entities/Enemies/Flower.gd +++ b/Scenes/Entities/Enemies/Flower.gd @@ -8,8 +8,13 @@ func _ready(): $Body/Bottom.play("default") add_to_group("enemies") + $Collision.init() $Collision.collision_area.set_collision_layer_value(Utilities.Collision.Layer.ENEMY, true) + + $Health.hit.connect(func(): + $Body/Top.visible = false + ) $Health.died.connect(func(): $Body.remove_child($Body/Top) ) diff --git a/Scenes/Entities/Enemies/Flowers.gd b/Scenes/Entities/Enemies/Flowers.gd index 5f8e974..9b6658e 100644 --- a/Scenes/Entities/Enemies/Flowers.gd +++ b/Scenes/Entities/Enemies/Flowers.gd @@ -28,9 +28,12 @@ func _ready(): var flower = FlowerScene.instantiate() flower.angle = deg_to_rad(120 * number) + flower.get_node("Health").hit.connect(func(): + flowers.remove_at(flowers.find(flower)) + ) + # if last flower is removed, remove self flower.get_node("Health").died.connect(func(): - flowers.remove_at(flowers.find(flower)) if flowers.is_empty(): queue_free() ) diff --git a/Scenes/Entities/Enemies/Slime.gd b/Scenes/Entities/Enemies/Slime.gd index 427b18f..fe67fca 100644 --- a/Scenes/Entities/Enemies/Slime.gd +++ b/Scenes/Entities/Enemies/Slime.gd @@ -5,7 +5,11 @@ func _ready(): add_to_group("enemies") get_node("Collision").init() + + get_node("Movement").init() -func _physics_process(delta): - get_node("Movement").physics_process(delta) +#func _physics_process(delta): + #pass + #print(position) + #get_node("Movement").physics_process(delta) diff --git a/Scenes/Entities/Enemies/Slime.tscn b/Scenes/Entities/Enemies/Slime.tscn index 558b736..dcaaf52 100644 --- a/Scenes/Entities/Enemies/Slime.tscn +++ b/Scenes/Entities/Enemies/Slime.tscn @@ -14,9 +14,6 @@ [ext_resource type="PackedScene" uid="uid://ce3vv2pod6auc" path="res://Scenes/Entities/Enemies/Components/Collision.tscn" id="7_kjjor"] [ext_resource type="PackedScene" uid="uid://b3i372vgdbxk" path="res://Scenes/Entities/Enemies/Components/Health.tscn" id="8_klsy3"] -[sub_resource type="CircleShape2D" id="CircleShape2D_f54tg"] -radius = 6.0 - [sub_resource type="SpriteFrames" id="SpriteFrames_4e1a7"] animations = [{ "frames": [{ @@ -65,24 +62,26 @@ animations = [{ "speed": 8.0 }] +[sub_resource type="CircleShape2D" id="CircleShape2D_f54tg"] +radius = 6.0 + [node name="Slime" type="CharacterBody2D"] collision_layer = 16 collision_mask = 188 script = ExtResource("1_2xftl") -[node name="CollisionShape2D" type="CollisionShape2D" parent="."] -position = Vector2(0, -6) -shape = SubResource("CircleShape2D_f54tg") - [node name="AnimatedSprite2D" type="AnimatedSprite2D" parent="."] texture_filter = 1 -position = Vector2(0, -6.25) sprite_frames = SubResource("SpriteFrames_4e1a7") +[node name="CollisionShape2D" type="CollisionShape2D" parent="."] +shape = SubResource("CircleShape2D_f54tg") + [node name="Movement" parent="." instance=ExtResource("6_u48ct")] entityPath = NodePath("..") spritePath = NodePath("../AnimatedSprite2D") -SPEED = 12 +component_collision_path = NodePath("../Collision") +SPEED = 1.0 timer_time = 5.0 [node name="Collision" parent="." instance=ExtResource("7_kjjor")] diff --git a/Scenes/Entities/Enemies/Snake.gd b/Scenes/Entities/Enemies/Snake.gd index a87ecf0..af09990 100644 --- a/Scenes/Entities/Enemies/Snake.gd +++ b/Scenes/Entities/Enemies/Snake.gd @@ -1,7 +1,7 @@ extends CharacterBody2D -@export var speed: float = 10 +@export var speed: float = 1 static var detected_bombs = [] var did_detect_bomb = false @@ -32,7 +32,9 @@ func _ready(): add_to_group("enemies") component_collision.init() + component_movement.SPEED = speed + component_movement.init() func _physics_process(delta): @@ -71,18 +73,19 @@ func _physics_process(delta): if $DetectionArea.get_overlapping_bodies().has(detected_bomb): _on_detection_area_body_entered(detected_bomb) elif did_detect_bomb: - component_movement.CURRENT_DIRECTION = detected_bomb_direction + component_movement.FIXED_DIRECTION = detected_bomb_direction - if not is_animating_state: - component_movement.physics_process(delta) + #if not is_animating_state: + #component_movement.physics_process(delta) func set_animating_state(state: bool): is_animating_state = state if is_animating_state: - component_movement.MovementTimer.stop() + component_movement.pause() + component_movement.FIXED_DIRECTION = null else: - component_movement.MovementTimer.start() + component_movement.unpause() func _on_detection_area_body_entered(_body): diff --git a/Scenes/Entities/Enemies/Snake.tscn b/Scenes/Entities/Enemies/Snake.tscn index 660b3d7..48a19ae 100644 --- a/Scenes/Entities/Enemies/Snake.tscn +++ b/Scenes/Entities/Enemies/Snake.tscn @@ -380,6 +380,7 @@ shape = SubResource("RectangleShape2D_7ji0i") [node name="Movement" parent="." instance=ExtResource("14_ab70e")] entityPath = NodePath("..") spritePath = NodePath("../AnimatedSprite2D") +SPEED = 1.0 timer_time = 2.0 follows = true follow_chance = 80 diff --git a/Scenes/Entities/Enemies/Tree.gd b/Scenes/Entities/Enemies/Tree.gd index bbd02a9..320640e 100644 --- a/Scenes/Entities/Enemies/Tree.gd +++ b/Scenes/Entities/Enemies/Tree.gd @@ -12,24 +12,20 @@ func _ready(): component_collision.init() component_collision.collision_area.set_collision_mask_value(Utilities.Collision.Layer.EXPLOSION, false) - component_movement.process_mode = Node.PROCESS_MODE_DISABLED - set_physics_process(false) $AnimatedSprite2D.play("spawn") $AnimatedSprite2D.stop() $AnimatedSprite2D.set_frame_and_progress(0, 0) - - $Health.connect("died", func(): - $Detection.set_collision_mask_value(Utilities.Collision.Layer.PLAYER, false) - ) -func _physics_process(delta): - component_movement.physics_process(delta) +#func _physics_process(delta): + #component_movement.physics_process(delta) func _on_detection_body_entered(_body): $AnimatedSprite2D.play("spawn") await $AnimatedSprite2D.animation_finished + component_collision.collision_area.set_collision_mask_value(Utilities.Collision.Layer.EXPLOSION, true) - component_movement.process_mode = Node.PROCESS_MODE_INHERIT - set_physics_process(true) + component_movement.init() + + $Detection.set_collision_mask_value(Utilities.Collision.Layer.PLAYER, false) diff --git a/Scenes/Entities/Enemies/Tree.tscn b/Scenes/Entities/Enemies/Tree.tscn index f216159..01a79bf 100644 --- a/Scenes/Entities/Enemies/Tree.tscn +++ b/Scenes/Entities/Enemies/Tree.tscn @@ -141,7 +141,7 @@ script = ExtResource("1_ktvfx") texture_filter = 1 position = Vector2(0, -8) sprite_frames = SubResource("SpriteFrames_c5ryj") -animation = &"death_post" +animation = &"spawn" [node name="CollisionShape2D" type="CollisionShape2D" parent="."] position = Vector2(0, -8) @@ -150,7 +150,8 @@ shape = SubResource("CapsuleShape2D_u8qfj") [node name="Movement" parent="." instance=ExtResource("17_wlky1")] entityPath = NodePath("..") spritePath = NodePath("../AnimatedSprite2D") -SPEED = 24 +component_collision_path = NodePath("../Collision") +SPEED = 1.4 timer_time = 2.0 follows = true follow_chance = 50 @@ -164,7 +165,7 @@ component_health_path = NodePath("../Health") entityPath = NodePath("..") spritePath = NodePath("../AnimatedSprite2D") component_movement_path = NodePath("../Movement") -health = 1 +health = 2 [node name="Detection" type="Area2D" parent="."] collision_layer = 64 -- cgit v1.2.3