115 lines
5.3 KiB
GDScript
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
|