109 lines
2.7 KiB
GDScript
109 lines
2.7 KiB
GDScript
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
|