Randoloot/scripts/game/engine_visual.gd
2026-10-09 20:59:55 +02:00

103 lines
3.8 KiB
GDScript

extends Node2D
const TRAIL_INTERVAL := 0.035
const MAX_TRAIL_PARTICLES := 90
var _ship: CharacterBody2D
var _thrust_strength := 0.0
var _engine_phase := 0.0
var _trail_emission_timer := 0.0
var _trail_particles: Array[Dictionary] = []
func _ready() -> void:
_ship = get_parent() as CharacterBody2D
set_as_top_level(true)
z_index = -1
if is_instance_valid(_ship):
global_position = _ship.global_position
global_rotation = _ship.global_rotation
func _process(delta: float) -> void:
if not is_instance_valid(_ship):
return
global_position = _ship.global_position
global_rotation = _ship.global_rotation
_engine_phase += delta
var thrust_active := Input.is_action_pressed("ship_thrust")
if bool(_ship.get("_is_destroyed")):
thrust_active = false
var target_strength := 1.0 if thrust_active else 0.0
_thrust_strength = move_toward(_thrust_strength, target_strength, 5.5 * delta)
if thrust_active:
_trail_emission_timer += delta
while _trail_emission_timer >= TRAIL_INTERVAL:
_trail_emission_timer -= TRAIL_INTERVAL
_spawn_trail_particle()
_update_trail_particles(delta)
queue_redraw()
func _spawn_trail_particle() -> void:
if _trail_particles.size() >= MAX_TRAIL_PARTICLES:
return
var aft := Vector2.DOWN.rotated(_ship.global_rotation)
var side := Vector2(-aft.y, aft.x)
var angle := randf_range(-0.18, 0.18)
var particle_direction := aft.rotated(angle)
var life := randf_range(0.45, 0.8)
_trail_particles.append({
"position": _ship.global_position + aft * 21.0,
"velocity": _ship.velocity + particle_direction * randf_range(30.0, 58.0) + side * randf_range(-6.0, 6.0),
"age": 0.0,
"life": life,
"size": randf_range(1.5, 3.0),
})
func _update_trail_particles(delta: float) -> void:
for particle_index in range(_trail_particles.size() - 1, -1, -1):
var particle := _trail_particles[particle_index]
particle["position"] = particle["position"] + particle["velocity"] * delta
particle["age"] = float(particle["age"]) + delta
_trail_particles[particle_index] = particle
if float(particle["age"]) >= float(particle["life"]):
_trail_particles.remove_at(particle_index)
func _draw() -> void:
_draw_trail()
if _thrust_strength <= 0.01:
return
var pulse := 0.82 + 0.18 * sin(_engine_phase * 25.0)
var length := (28.0 + pulse * 14.0) * _thrust_strength
var base_y := 22.0
var outer_tip := base_y + length
var inner_tip := base_y + length * 0.76
var core_tip := base_y + length * 0.48
draw_colored_polygon(PackedVector2Array([
Vector2(-5.2, base_y), Vector2(-3.2, base_y + 6.0), Vector2(0.0, outer_tip),
Vector2(3.2, base_y + 6.0), Vector2(5.2, base_y),
]), Color(0.04, 0.58, 1.0, 0.48 * _thrust_strength))
draw_colored_polygon(PackedVector2Array([
Vector2(-2.8, base_y), Vector2(-1.8, base_y + 4.0), Vector2(0.0, inner_tip),
Vector2(1.8, base_y + 4.0), Vector2(2.8, base_y),
]), Color(0.24, 0.9, 1.0, 0.78 * _thrust_strength))
draw_colored_polygon(PackedVector2Array([
Vector2(-1.0, base_y), Vector2(0.0, core_tip), Vector2(1.0, base_y),
]), Color(0.88, 0.98, 1.0, 0.92 * _thrust_strength))
draw_circle(Vector2(0.0, base_y), 2.3, Color(0.42, 0.88, 1.0, 0.82 * _thrust_strength))
func _draw_trail() -> void:
for particle in _trail_particles:
var age := float(particle["age"])
var life := float(particle["life"])
var fade := 1.0 - clampf(age / life, 0.0, 1.0)
var current_position: Vector2 = particle["position"]
var particle_velocity: Vector2 = particle["velocity"]
var particle_size := float(particle["size"])
var current_local := to_local(current_position)
var tail_local := to_local(current_position - particle_velocity.normalized() * particle_size * 3.5)
draw_line(tail_local, current_local, Color(0.22, 0.78, 1.0, fade * 0.52), particle_size * 0.72, true)
draw_circle(current_local, particle_size * fade, Color(0.62, 0.94, 1.0, fade * 0.72))