103 lines
3.8 KiB
GDScript
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))
|