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/Components/Movement.gd | 281 +++++++++++++++++-------- 1 file changed, 198 insertions(+), 83 deletions(-) (limited to 'Scenes/Entities/Enemies/Components/Movement.gd') 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 -- cgit v1.2.3