Files
rewave/scenes/characters/Enemy.gd
2024-02-08 22:16:58 +01:00

136 lines
3.1 KiB
GDScript

extends CharacterBody2D
class_name Enemy
"""
This implements a very rudimentary state machine. There are better implementations
in the AssetLib if you want to make something more complex. Also it shares code with Enemy.gd
and probably both should extend some parent script
"""
@export var WALK_SPEED: int = 350
@export var ROLL_SPEED: int = 1000
@export var hitpoints: int = 3
var despawn_fx = preload("res://scenes/misc/DespawnFX.tscn")
var linear_vel = Vector2()
@export var facing = "down" # (String, "up", "down", "left", "right")
var anim = ""
var new_anim = ""
enum { STATE_IDLE, STATE_WALKING, STATE_ATTACK, STATE_ROLL, STATE_DIE, STATE_HURT }
var state = STATE_IDLE
func _ready():
randomize()
func _physics_process(_delta):
match state:
STATE_IDLE:
new_anim = "idle_" + facing
STATE_WALKING:
set_velocity(linear_vel)
move_and_slide()
linear_vel = velocity
var target_speed = Vector2()
if facing == "down":
target_speed += Vector2.DOWN
if facing == "left":
target_speed += Vector2.LEFT
if facing == "right":
target_speed += Vector2.RIGHT
if facing == "up":
target_speed += Vector2.UP
target_speed *= WALK_SPEED
linear_vel = linear_vel.lerp(target_speed, 0.9)
new_anim = ""
if abs(linear_vel.x) > abs(linear_vel.y):
if linear_vel.x < 0:
facing = "left"
if linear_vel.x > 0:
facing = "right"
if abs(linear_vel.y) > abs(linear_vel.x):
if linear_vel.y < 0:
facing = "up"
if linear_vel.y > 0:
facing = "down"
if linear_vel != Vector2.ZERO:
new_anim = "walk_" + facing
else:
state = STATE_IDLE
pass
STATE_ATTACK:
new_anim = "slash_" + facing
pass
STATE_ROLL:
set_velocity(linear_vel)
move_and_slide()
linear_vel = velocity
var target_speed = Vector2()
if facing == "up":
target_speed.y = -1
if facing == "down":
target_speed.y = 1
if facing == "left":
target_speed.x = -1
if facing == "right":
target_speed.x = 1
target_speed *= ROLL_SPEED
linear_vel = linear_vel.lerp(target_speed, 0.9)
new_anim = "roll"
pass
STATE_DIE:
new_anim = "die"
STATE_HURT:
new_anim = "hurt"
if new_anim != anim:
anim = new_anim
$anims.play(anim)
pass
func goto_idle():
state = STATE_IDLE
func _on_state_changer_timeout():
$state_changer.wait_time = randf_range(1.0, 5.0)
#state = randi() %3
state = STATE_ATTACK
facing = ["left", "right", "up", "down"][randi()%3]
pass # Replace with function body.
func _on_hurtbox_area_entered(area):
if state != STATE_DIE and area.name == "player_sword":
hitpoints -= 1
var pushback_direction = (global_position - area.global_position).normalized()
set_velocity(pushback_direction * 5000)
move_and_slide()
state = STATE_HURT
$state_changer.start()
if hitpoints <= 0:
$state_changer.stop()
state = STATE_DIE
pass # Replace with function body.
func despawn():
var despawn_particles = despawn_fx.instantiate()
get_parent().add_child(despawn_particles)
despawn_particles.global_position = global_position
if has_node("item_spawner"):
get_node("item_spawner").spawn()
queue_free()
pass