Randoloot/scripts/game/engine_visual.gd
2026-10-25 22:38:13 +01:00

115 lines
5.3 KiB
GDScript

extends Node2D
const TRAIL_INTERVAL := 0.025
const MAX_TRAIL_PARTICLES := 96
const PROFILES := {
"szerszen":{"color":Color("5dbdff"),"nozzles":[Vector2(-6.5,26),Vector2(6.5,26)],"width":11.0},
"bastion":{"color":Color("ffb45c"),"nozzles":[Vector2(-22,24),Vector2(0,27),Vector2(22,24)],"width":13.0},
"wedrowiec":{"color":Color("55f1df"),"nozzles":[Vector2(-9.5,23),Vector2(0,27),Vector2(9.5,23)],"width":9.0},
"zmija":{"color":Color("bf7cff"),"nozzles":[Vector2(-13,23),Vector2(0,26),Vector2(13,23)],"width":11.0}
}
var _ship: CharacterBody2D
var _thrust_strength := 0.0
var _engine_phase := 0.0
var _trail_emission_timer := 0.0
var _trail_particles: Array[Dictionary] = []
var _mini_boost := false
var _boost_strength := 0.0
var _profile: Dictionary
var _plumes: Array[ShaderMaterial] = []
var _rcs: Array[ShaderMaterial] = []
var _maneuver := Vector3.ZERO
var _previous_position := Vector2.ZERO
func _ready() -> void:
_ship = get_parent() as CharacterBody2D
set_as_top_level(true)
z_index = -1
_profile = PROFILES[preload("res://scripts/game/ship_catalog.gd").for_path(GameState.selected_ship_path).asset]
for nozzle in _profile.nozzles:
_plumes.append(_add_plume(nozzle,0.0,float(_profile.width),90.0))
for port in [[Vector2(-10,-16),PI*0.5],[Vector2(10,-16),-PI*0.5],[Vector2(-15,12),PI*0.5],[Vector2(15,12),-PI*0.5],[Vector2(-7,-23),PI],[Vector2(7,-23),PI]]:
_rcs.append(_add_plume(port[0],float(port[1]),6.0,36.0))
global_position = _ship.global_position
global_rotation = _ship.global_rotation
_previous_position = global_position
func _add_plume(at: Vector2, angle: float, width: float, length: float) -> ShaderMaterial:
var mount := Node2D.new()
mount.position = at
mount.rotation = angle
add_child(mount)
var quad := ColorRect.new()
quad.mouse_filter = Control.MOUSE_FILTER_IGNORE
quad.position = Vector2(-width*0.5,0)
quad.size = Vector2(width,length)
var material := ShaderMaterial.new()
material.shader = preload("res://scripts/game/thruster_plume.gdshader")
material.set_shader_parameter("plume_color",_profile.color)
material.set_shader_parameter("phase",float(_plumes.size()+_rcs.size())*8.7)
quad.material = material
mount.add_child(quad)
return material
func _process(delta: float) -> void:
if not is_instance_valid(_ship): return
global_position = _ship.global_position
global_rotation = _ship.global_rotation
if global_position.distance_to(_previous_position) > 400: _trail_particles.clear()
_previous_position = global_position
_engine_phase += delta
var active := not bool(_ship.get("_is_destroyed")) and not bool(_ship.get("is_docked"))
_mini_boost = active and bool(_ship.call("is_mini_boosting"))
var boosted := active and bool(_ship.call("is_boosting"))
var thrust_active := active and (Input.is_action_pressed("ship_thrust") or boosted)
var target_strength := (1.0 if thrust_active else 0.0)
_thrust_strength = move_toward(_thrust_strength,target_strength,delta*(9.0 if thrust_active else 6.0))
_boost_strength = move_toward(_boost_strength,1.0 if boosted else 0.0,delta*7.0)
if not active:
_thrust_strength = 0.0
_trail_particles.clear()
for plume in _plumes:
plume.set_shader_parameter("power",_thrust_strength)
plume.set_shader_parameter("boost",_boost_strength)
var yaw := Input.get_axis("ship_turn_left","ship_turn_right") if active else 0.0
var strafe := Input.get_axis("ship_strafe_left","ship_strafe_right") if active else 0.0
var braking := 1.0 if active and Input.is_action_pressed("ship_brake") else 0.0
_maneuver = _maneuver.move_toward(Vector3(yaw,strafe,braking),delta*12.0)
var powers := [maxf(_maneuver.x,0.0)+maxf(_maneuver.y,0.0),maxf(-_maneuver.x,0.0)+maxf(-_maneuver.y,0.0),maxf(-_maneuver.x,0.0)+maxf(_maneuver.y,0.0),maxf(_maneuver.x,0.0)+maxf(-_maneuver.y,0.0),_maneuver.z,_maneuver.z]
for i in _rcs.size(): _rcs[i].set_shader_parameter("power",minf(0.85,float(powers[i])))
if thrust_active:
_trail_emission_timer += delta
var emitted := 0
while _trail_emission_timer >= TRAIL_INTERVAL and emitted < 8:
_trail_emission_timer -= TRAIL_INTERVAL
_spawn_trail_particle()
emitted += 1
_trail_emission_timer = minf(_trail_emission_timer,TRAIL_INTERVAL)
_update_trail_particles(delta)
queue_redraw()
func _spawn_trail_particle() -> void:
for index in _profile.nozzles.size():
if _trail_particles.size() >= MAX_TRAIL_PARTICLES: break
var aft := Vector2.DOWN.rotated(global_rotation)
_trail_particles.append({"position":_ship.to_global(_profile.nozzles[index]),"velocity":_ship.velocity*0.12+aft*(42.0 if _mini_boost else 20.0),"age":0.0,"life":0.48 if _mini_boost else 0.28,"size":2.3 if _mini_boost else 1.5,"boost":_mini_boost,"lane":index})
func _update_trail_particles(delta: float) -> void:
for i in range(_trail_particles.size()-1,-1,-1):
var p := _trail_particles[i]
p.position += p.velocity*delta
p.age += delta
if p.age >= p.life: _trail_particles.remove_at(i)
func _draw() -> void:
var previous := {}
for p in _trail_particles:
var fade := 1.0-float(p.age)/float(p.life)
var point := to_local(p.position)
var lane: int = p.lane
if previous.has(lane):
var prior: Vector2 = previous[lane]
if point.distance_to(prior)<60:
draw_line(prior,point,Color(_profile.color,fade*0.055),float(p.size)*4.0,true)
draw_line(prior,point,Color(_profile.color,fade*0.25),float(p.size)*0.8,true)
previous[lane] = point