95 lines
3.5 KiB
GDScript
95 lines
3.5 KiB
GDScript
extends CharacterBody2D
|
|
|
|
const DAMAGE_POPUP_SCENE := preload("res://scenes/game/damage_popup.tscn")
|
|
const IMPACT_EFFECT_SCENE := preload("res://scenes/game/impact_effect.tscn")
|
|
const PLASMA_PROJECTILE_SCENE := preload("res://scenes/game/enemy_plasma_projectile.tscn")
|
|
const WEAPON_AUDIO_SCRIPT := preload("res://scripts/game/weapon_audio.gd")
|
|
|
|
@export var max_hull := 50.0
|
|
@export var activation_range := 760.0
|
|
@export var approach_speed := 62.0
|
|
@export var approach_acceleration := 85.0
|
|
@export var turn_speed := 1.8
|
|
@export var weapon_range := 680.0
|
|
@export var weapon_cooldown := 1.5
|
|
@export var weapon_damage := 8.0
|
|
|
|
var hull := 50.0
|
|
var _player: CharacterBody2D
|
|
var _activated := false
|
|
var _sprite: Sprite2D
|
|
var _weapon_timer := 0.0
|
|
|
|
func _ready() -> void:
|
|
hull = max_hull
|
|
_sprite = $Sprite2D
|
|
add_to_group("enemies")
|
|
_weapon_timer = randf_range(0.2, weapon_cooldown)
|
|
|
|
func configure(player: CharacterBody2D, ship_texture: Texture2D) -> void:
|
|
_player = player
|
|
_sprite = $Sprite2D
|
|
_sprite.texture = ship_texture
|
|
var largest_dimension := maxf(ship_texture.get_width(), ship_texture.get_height())
|
|
_sprite.scale = Vector2.ONE * (56.0 / largest_dimension)
|
|
|
|
func _physics_process(delta: float) -> void:
|
|
if not is_instance_valid(_player):
|
|
velocity = velocity.move_toward(Vector2.ZERO, approach_acceleration * delta)
|
|
move_and_slide()
|
|
return
|
|
|
|
var to_player := _player.global_position - global_position
|
|
if to_player.length() <= activation_range:
|
|
_activated = true
|
|
if _activated and to_player.length_squared() > 1.0:
|
|
var direction := to_player.normalized()
|
|
var desired_rotation := direction.angle() + PI * 0.5
|
|
rotation = rotate_toward(rotation, desired_rotation, turn_speed * delta)
|
|
velocity = velocity.move_toward(direction * approach_speed, approach_acceleration * delta)
|
|
_weapon_timer = maxf(0.0, _weapon_timer - delta)
|
|
if to_player.length() <= weapon_range and _weapon_timer <= 0.0:
|
|
_fire_plasma(direction)
|
|
_weapon_timer = weapon_cooldown
|
|
else:
|
|
velocity = velocity.move_toward(Vector2.ZERO, approach_acceleration * delta)
|
|
|
|
move_and_slide()
|
|
_check_player_collision()
|
|
|
|
func _check_player_collision() -> void:
|
|
for collision_index in get_slide_collision_count():
|
|
var collision := get_slide_collision(collision_index)
|
|
if collision.get_collider() == _player and _player.has_method("register_enemy_collision"):
|
|
_player.call("register_enemy_collision", global_position)
|
|
|
|
func _fire_plasma(direction: Vector2) -> void:
|
|
var projectile := PLASMA_PROJECTILE_SCENE.instantiate() as Area2D
|
|
projectile.call("configure", global_position + direction * 28.0, direction, weapon_damage)
|
|
get_parent().add_child(projectile)
|
|
WEAPON_AUDIO_SCRIPT.play(get_parent(), global_position, ItemDefinition.WeaponKind.PLASMA, -10.0)
|
|
|
|
func take_damage(amount: float) -> void:
|
|
hull = maxf(0.0, hull - amount)
|
|
_show_damage_popup(amount)
|
|
if hull <= 0.0:
|
|
_spawn_destruction_effect()
|
|
queue_free()
|
|
|
|
func _spawn_destruction_effect() -> void:
|
|
var effect := IMPACT_EFFECT_SCENE.instantiate() as Node2D
|
|
effect.global_position = global_position
|
|
get_parent().add_child(effect)
|
|
effect.call("configure", true, Color(1.0, 0.36, 0.18))
|
|
|
|
func _show_damage_popup(amount: float) -> void:
|
|
var popup := DAMAGE_POPUP_SCENE.instantiate() as Label
|
|
popup.text = "-%s DMG" % _format_damage(amount)
|
|
popup.global_position = global_position + Vector2(randf_range(-16.0, 16.0), -28.0)
|
|
get_parent().add_child(popup)
|
|
|
|
func _format_damage(amount: float) -> String:
|
|
if is_equal_approx(amount, roundf(amount)):
|
|
return str(int(roundf(amount)))
|
|
return "%.1f" % amount
|