class_name Enemy extends Creature enum State { IDLE, CHASE, ATTACK } @export_category("Behavior") @export var state: State = State.IDLE ## Speed the enemy will chase the player @export var chase_speed: float = 25 ## Distance the enemy will chase the player before attacking @export var attack_distance: float = 10 ## Maximum distance the enemy will chase the player before giving up @export var max_chase_distance: float = 200 @export_category("Parts") ## The area that will detect players @export var animation_player: AnimationPlayer ## The area that will detect players @export var sprite: Sprite2D @export var detection_area: Area2D var _chase_target: Node2D var _target_is_left: bool = false func _play_animation(animation: String) -> void: if not animation_player: return if not animation_player.has_animation(animation): return if animation_player.is_playing() and animation_player.current_animation == animation: return animation_player.play(animation) func _on_ready() -> void: self.detection_area.body_entered.connect(self._on_detection_area_entered) func _process(_delta: float) -> void: var animation_name = str(State.keys()[self.state]).to_lower() self._play_animation(animation_name) sprite.flip_h = self._target_is_left var distance: float = 0 if self._chase_target: var target_position: Vector2 = self._chase_target.position self._target_is_left = target_position.x < self.position.x distance = target_position.distance_to(self.position) match self.state: State.IDLE: pass State.CHASE: if not self._chase_target: self.state = State.IDLE return if distance < self.attack_distance: self.state = State.ATTACK return if distance > self.max_chase_distance: self._chase_target = null self.state = State.IDLE return State.ATTACK: if distance > self.attack_distance: self.state = State.CHASE return func _physics_process(delta: float) -> void: match self.state: State.CHASE: if not self._chase_target: return # lmanley: This is super basic movement logic for test # it will need to be updated to actually be able to # path, jump, etc. var target_position: Vector2 = self._chase_target.position var direction: Vector2 = target_position - self.position direction = direction.normalized() self.velocity += direction * self.chase_speed * delta State.IDLE: self.velocity.x = 0 super._physics_process(delta) func _on_detection_area_entered(body: CollisionObject2D) -> void: match state: State.IDLE: # If not already chasing a target and the body is a player, start chasing if not self._chase_target and body is Player: self._chase_target = body self.state = State.CHASE