1
Fork 0
mirror of https://github.com/Steffo99/watermelonkeys-patched-ld51.git synced 2024-11-23 00:24:17 +00:00
fading-sun/enemies/Enemy.gd
AndreaTerenz f31eb7d496 lights
2022-10-03 16:32:11 +02:00

186 lines
4.5 KiB
GDScript

class_name Enemy
extends KinematicBody2D
enum STATES {
SPAWN,
ROAM, # fly around until player is in reach
AGGRO, # get mad because you saw the player
CHARGE, #RUN to the player
ATTACK #fuck up the player if the sucker didnt run away
}
export(float, 2.0, 150.0, 0.1) var attack_dist = 150.0
export(float, 1.0, 500.0, 0.1) var roam_max_speed = 100.0
export(float, 1.0, 200.0, 0.1) var attack_speed_mul = 10.0
export(float, 0.01, 1.0, 0.01) var roam_acceleration = 0.4
export(float, 0.01, 5.0, 0.01) var aggro_timer_len = 2.0
onready var ray := $RayCast2D
onready var anim_sprite := $AnimatedSprite
var aggro_timer := Timer.new()
var noise_idx := 0.0
var noise := OpenSimplexNoise.new()
var state = STATES.SPAWN
var player : Giovanna = null
var velocity := Vector2.ZERO
var dir := Vector2.RIGHT
var charge_target := Vector2.ZERO
var charge_collision : KinematicCollision2D = null
var charge_blocked := false
var charge_dist_left = -1.0
var spawn_done := false
func _ready():
add_child(aggro_timer)
aggro_timer.one_shot = true
aggro_timer.wait_time = aggro_timer_len
anim_sprite.animation = "spawning"
anim_sprite.playing = true
# Configure noise
randomize()
noise.seed = randi()
noise.octaves = 2
noise.period = 20.0
noise.persistence = 0.8
# yield(get_tree(), "idle_frame")
# Gets reference to the player from the root node
player = owner.get_meta("player")
func _physics_process(delta):
var new_s = check_state()
if state != new_s:
state = new_s
init_state()
run_state(delta)
func check_state():
if not player:
return STATES.ROAM
match state:
STATES.SPAWN:
if spawn_done:
return STATES.ROAM
STATES.ROAM:
var p_pos = player.global_position
# let's be efficient and use the squared distance
var dist = global_position.distance_squared_to(p_pos)
if dist <= pow(attack_dist, 2):
# it's in range
ray.cast_to = ray.to_local(p_pos)
ray.force_raycast_update()
var coll = ray.get_collider()
if coll and coll == player:
# LADIES N GENTLEMEN WE GOT HIM
return STATES.AGGRO
STATES.AGGRO:
if aggro_timer.time_left <= 0.0:
return STATES.CHARGE
STATES.CHARGE:
var reached_player = (charge_collision and charge_collision.collider == player)
var close_enough = charge_dist_left <= pow(5.0, 2)
if reached_player:
return STATES.ATTACK
if close_enough or charge_blocked:
# we got to the targeted position, but
# found no Giovanna there...
return STATES.ROAM
STATES.ATTACK:
return state
if dist_to_player() > 20.0:
return STATES.ROAM
return state
func init_state():
# Things to do when the state changes
match state:
STATES.SPAWN:
# nothing to do
pass
STATES.ROAM:
anim_sprite.modulate = Color.white
velocity *= 0.0
dir = Vector2.RIGHT
anim_sprite.animation = "roaming"
anim_sprite.playing = true
STATES.AGGRO:
velocity *= 0.0
dir = Vector2.RIGHT
aggro_timer.start()
charge_target = player.position
STATES.CHARGE:
charge_collision = null
anim_sprite.offset *= 0.0
STATES.ATTACK:
## TEMP
velocity *= 0.0
anim_sprite.modulate = Color.red
func run_state(delta):
match state:
STATES.SPAWN:
# nothing to do
pass
STATES.ROAM:
noise_idx += delta * 100
var _n = noise.get_noise_1d(noise_idx)
var n = range_lerp(_n, -1.0, 1.0, -TAU/4.0, TAU/4.0)
dir = dir.linear_interpolate(dir.rotated(n * 0.1), 0.5)
velocity = velocity.linear_interpolate(dir * roam_max_speed, roam_acceleration)
var coll = move_and_collide(velocity * delta)
var coll_horizontal := false
if coll:
var norm = coll.normal
if norm.y == 0:
# vertical wall
dir.x *= -1
velocity.x *= -1
else:
dir.y *= -1
velocity.y *= -1
anim_sprite.flip_h = (velocity.x > 0)
STATES.AGGRO:
var r = 2.0
anim_sprite.offset = Vector2(rand_range(-r, r), rand_range(-r, r))
STATES.CHARGE:
charge_dist_left = position.distance_squared_to(charge_target)
var target_dir = position.direction_to(charge_target)
var speed = roam_max_speed * attack_speed_mul
var fac = charge_dist_left/pow(attack_dist, 2)
velocity = velocity.linear_interpolate(target_dir * speed, fac)
var output_vel = move_and_slide(velocity)
if get_slide_count() > 0:
charge_collision = get_slide_collision(0)
if output_vel.length() == 0.0:
charge_blocked = true
STATES.ATTACK:
pass
func dist_to_player():
return position.distance_to(player.position)
func _on_AnimatedSprite_animation_finished():
if anim_sprite.animation == "spawning":
spawn_done = true