summaryrefslogtreecommitdiff
path: root/Scenes/Entities/Enemies/Components
diff options
context:
space:
mode:
Diffstat (limited to 'Scenes/Entities/Enemies/Components')
-rw-r--r--Scenes/Entities/Enemies/Components/Health.gd37
-rw-r--r--Scenes/Entities/Enemies/Components/Movement.gd281
2 files changed, 225 insertions, 93 deletions
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