Make boss encounter more dynamic
This commit is contained in:
parent
471a43e8a6
commit
cb6b0b69c6
6 changed files with 60 additions and 9 deletions
|
|
@ -5,6 +5,8 @@ signal destroyed
|
|||
signal health_changed(current: int, maximum: int)
|
||||
|
||||
const COMBAT_TARGET = preload("res://core/CombatTarget.gd")
|
||||
const IRIS_COLOR := Color(0.25, 0.92, 1.0)
|
||||
const PUPIL_COLOR := Color(1.0, 0.9, 0.3)
|
||||
|
||||
@export var max_hp: int = 5
|
||||
|
||||
|
|
@ -69,7 +71,7 @@ func _draw() -> void:
|
|||
var pulse: float = 0.78 + 0.22 * sin(phase * 5.0)
|
||||
draw_set_transform(Vector2.ZERO, 0.0, Vector2(1.0, 0.66))
|
||||
NeonDraw.draw_glowing_circle(self, Vector2.ZERO, 25.0,
|
||||
Color(0.25, 0.92, 1.0), pulse, dark)
|
||||
IRIS_COLOR, pulse, dark)
|
||||
NeonDraw.draw_glowing_circle(self, Vector2.ZERO, 10.0,
|
||||
Color(1.0, 0.9, 0.3), 1.0, dark)
|
||||
PUPIL_COLOR, 1.0, dark)
|
||||
draw_set_transform(Vector2.ZERO, 0.0, Vector2.ONE)
|
||||
|
|
|
|||
|
|
@ -21,12 +21,20 @@ const MAX_ACTIVE_MINIONS: int = 16
|
|||
const GOLDEN_WAVE_PERIOD: int = 3
|
||||
const CORE_MAX_HEALTH: int = 36
|
||||
const REDRAW_INTERVAL: float = 1.0 / 12.0
|
||||
const ARMOURED_IRIS_COLOR := Color(0.72, 0.22, 1.0)
|
||||
const ARMOURED_PUPIL_COLOR := Color(0.18, 1.0, 0.62)
|
||||
const EXPOSED_IRIS_COLOR := Color(1.0, 0.56, 0.08)
|
||||
const EXPOSED_PUPIL_COLOR := Color(1.0, 0.94, 0.42)
|
||||
|
||||
@export var first_wave_delay: float = 1.5
|
||||
@export var wave_interval: float = 6.0
|
||||
@export var minions_per_wave: int = 7
|
||||
@export var laser_interval: float = 3.5
|
||||
@export var laser_charge_time: float = 0.85
|
||||
@export var laser_interval: float = 2.25
|
||||
@export var laser_charge_time: float = 0.7
|
||||
@export var move_speed: float = 115.0
|
||||
@export var move_acceleration: float = 180.0
|
||||
@export var preferred_fleet_range: float = 880.0
|
||||
@export var strafe_speed: float = 72.0
|
||||
|
||||
var phase: int = Phase.MINION_WAVES
|
||||
var wave_timer: float = 0.0
|
||||
|
|
@ -43,6 +51,7 @@ var total_max_health: int = CORE_MAX_HEALTH
|
|||
var core_health: int = CORE_MAX_HEALTH
|
||||
var core_exposed: bool = false
|
||||
var combat_active: bool = true
|
||||
var movement_velocity: Vector2 = Vector2.ZERO
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
|
|
@ -77,6 +86,7 @@ func _process(delta: float) -> void:
|
|||
if phase == Phase.DEFEATED or not combat_active:
|
||||
return
|
||||
animation_phase += delta
|
||||
_move_around_fleet(delta)
|
||||
|
||||
wave_timer -= delta
|
||||
if wave_timer <= 0.0:
|
||||
|
|
@ -94,6 +104,31 @@ func _process(delta: float) -> void:
|
|||
queue_redraw()
|
||||
|
||||
|
||||
func _move_around_fleet(delta: float) -> void:
|
||||
var fleet: Node2D = get_tree().get_first_node_in_group("player_fleet")
|
||||
if fleet == null or fleet.ships.is_empty():
|
||||
movement_velocity = movement_velocity.move_toward(Vector2.ZERO,
|
||||
move_acceleration * delta)
|
||||
return
|
||||
var from_fleet: Vector2 = global_position - fleet.get_centroid()
|
||||
if from_fleet.length_squared() < 1.0:
|
||||
from_fleet = Vector2.UP
|
||||
var away: Vector2 = from_fleet.normalized()
|
||||
# Close or open the range while continuously strafing around the fleet.
|
||||
# Acceleration keeps the large creature drifting rather than snapping when
|
||||
# the player crosses it, and the speed cap makes its orbit predictable.
|
||||
var range_error: float = from_fleet.length() - preferred_fleet_range
|
||||
var radial_speed: float = clampf(range_error * 0.8, -move_speed, move_speed)
|
||||
var desired_velocity: Vector2 = -away * radial_speed \
|
||||
+ away.orthogonal() * strafe_speed
|
||||
if phase == Phase.CORE_EXPOSED:
|
||||
desired_velocity *= 0.7
|
||||
desired_velocity = desired_velocity.limit_length(move_speed)
|
||||
movement_velocity = movement_velocity.move_toward(desired_velocity,
|
||||
move_acceleration * delta)
|
||||
global_position += movement_velocity * delta
|
||||
|
||||
|
||||
func spawn_wave() -> void:
|
||||
if not combat_active or phase == Phase.CORE_EXPOSED or phase == Phase.DEFEATED:
|
||||
return
|
||||
|
|
@ -303,10 +338,10 @@ func _draw() -> void:
|
|||
# The central eye watches but is armoured; only tentacle eyes opened by a
|
||||
# returning marked minion join the combat-target group.
|
||||
draw_set_transform(Vector2.ZERO, 0.0, Vector2(0.72, 1.0))
|
||||
var core_color := Color(1.0, 0.78, 0.18) if core_exposed \
|
||||
else Color(0.28, 0.92, 1.0)
|
||||
var core_color := EXPOSED_IRIS_COLOR if core_exposed else ARMOURED_IRIS_COLOR
|
||||
NeonDraw.draw_glowing_circle(self, Vector2.ZERO, 31.0,
|
||||
core_color, 0.8 + 0.2 * sin(animation_phase * 3.0), dark)
|
||||
NeonDraw.draw_glowing_circle(self, Vector2.ZERO, 12.0,
|
||||
Color(1.0, 0.82, 0.2), 1.0, dark)
|
||||
EXPOSED_PUPIL_COLOR if core_exposed else ARMOURED_PUPIL_COLOR,
|
||||
1.0, dark)
|
||||
draw_set_transform(Vector2.ZERO, 0.0, Vector2.ONE)
|
||||
|
|
|
|||
Loading…
Reference in a new issue