Randoloot/scripts/game/freighter_warp_departure.gd
2026-10-25 16:12:08 +01:00

150 lines
6.5 KiB
GDScript

extends Control
signal finished
const DURATION := 4.0
const SHIP := preload("res://assets/planets/freighter.png")
var start_position := Vector2.ZERO
var destination_name := "ODLEGŁY SEKTOR"
var elapsed := 0.0
var _ship: Sprite2D
var _flash: ColorRect
var _title: Label
var _status: Label
var _stars: Array[Vector3] = []
var _done := false
func _ready() -> void:
process_mode = Node.PROCESS_MODE_ALWAYS
set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT)
mouse_filter = Control.MOUSE_FILTER_STOP
var rng := RandomNumberGenerator.new()
rng.seed = 872901
for star in 170: _stars.append(Vector3(rng.randf(),rng.randf(),rng.randf_range(0.3,1.0)))
_ship = Sprite2D.new()
_ship.texture = SHIP
_ship.texture_filter = CanvasItem.TEXTURE_FILTER_LINEAR_WITH_MIPMAPS
add_child(_ship)
_flash = ColorRect.new()
_flash.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT)
_flash.mouse_filter = Control.MOUSE_FILTER_IGNORE
add_child(_flash)
_title = _label(destination_name.to_upper(),18,Color("c4f3ff"))
_status = _label("INICJALIZACJA NAPĘDU SKOKOWEGO",11,Color("6eaeba"))
_play_audio()
_update_frame()
func _label(value: String, font_size: int, color: Color) -> Label:
var label := Label.new()
label.text = value
label.mouse_filter = Control.MOUSE_FILTER_IGNORE
label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
label.add_theme_font_size_override("font_size",font_size)
label.add_theme_color_override("font_color",color)
label.add_theme_color_override("font_outline_color",Color("020810"))
label.add_theme_constant_override("outline_size",5)
add_child(label)
return label
func _input(_event: InputEvent) -> void:
get_viewport().set_input_as_handled()
func _process(delta: float) -> void:
elapsed = minf(DURATION,elapsed+delta)
_update_frame()
if elapsed >= DURATION and not _done:
_done = true
finished.emit()
func _update_frame() -> void:
var charge := smoothstep(0.0,0.9,elapsed)
var acceleration := smoothstep(0.8,2.6,elapsed)
var jump := smoothstep(2.6,3.15,elapsed)
var center := Vector2(size.x*0.5,size.y*0.64)
var departure := start_position if start_position != Vector2.ZERO else center
var ship_position := departure.lerp(center,charge)
ship_position.y -= size.y*(0.16*acceleration+0.24*jump)
var height := lerpf(285.0,minf(440.0,size.y*0.61),charge)
height *= 1.0-jump*0.93
_ship.position = ship_position
_ship.scale = Vector2(height/SHIP.get_height()*(1.0-jump*0.6),height/SHIP.get_height())
_ship.modulate = Color(1.0+acceleration*0.3,1.0+acceleration*0.5,1.0+acceleration*0.7,1.0-jump)
_ship.visible = elapsed < 3.18
var flash := exp(-pow((elapsed-3.15)/0.10,2.0))*0.9
var blackout := smoothstep(3.55,DURATION,elapsed)
_flash.color = Color(0.55,0.87,1.0,flash) if flash > blackout else Color(0.015,0.025,0.045,blackout)
_title.position = Vector2(0,28)
_title.size = Vector2(size.x,30)
_status.position = Vector2(0,61)
_status.size = Vector2(size.x,22)
_status.text = "SKOK WARP" if elapsed > 2.6 else ("PRZYSPIESZANIE · TRASA ZABEZPIECZONA" if elapsed > 0.9 else "INICJALIZACJA NAPĘDU SKOKOWEGO")
_title.modulate.a = 1.0-blackout
_status.modulate.a = 1.0-blackout
queue_redraw()
func _draw() -> void:
var charge := smoothstep(0.0,0.9,elapsed)
var acceleration := smoothstep(0.8,2.6,elapsed)
var jump := smoothstep(2.6,3.15,elapsed)
draw_rect(Rect2(Vector2.ZERO,size),Color(0.005,0.014,0.03,charge*0.96))
for star in _stars:
var y := fmod(star.y*size.y+elapsed*(18.0+acceleration*180.0+jump*1200.0)*star.z,size.y+160.0)-80.0
var point := Vector2(star.x*size.x,y)
var length := 1.0+acceleration*star.z*34.0+jump*star.z*150.0
draw_line(point,point+Vector2(0,length),Color(0.4,0.75,1.0,charge*star.z*0.55),1.0,true)
if _ship != null and _ship.visible and jump < 0.98:
var height: float = SHIP.get_height()*_ship.scale.y
var tail: Vector2 = _ship.position+Vector2(0,height*0.45)
var power := (0.2+charge*0.5+acceleration*0.7)*(1.0-jump)
for side in [-1.0,1.0]:
var nozzle := tail+Vector2(side*height*0.075,0)
for halo in range(6,0,-1): draw_circle(nozzle,halo*7.0*power,Color(0.1,0.7,1.0,0.018*power))
var flame := (35.0+acceleration*170.0)*power*(0.94+sin(elapsed*71.0)*0.06)
for layer in 3:
var width := (13.0-layer*3.2)*power
var tip := nozzle+Vector2(sin(elapsed*43.0+side)*minf(4.0,width*0.2),flame*(1.0-layer*0.2))
var colors := [Color(0.08,0.4,1.0,0.25),Color(0.2,0.85,1.0,0.65),Color(0.85,1.0,1.0,0.95)]
draw_colored_polygon(PackedVector2Array([nozzle+Vector2(-width,-8),nozzle+Vector2(width,-8),nozzle+Vector2(width*0.65,flame*0.3),tip,nozzle+Vector2(-width*0.65,flame*0.3)]),colors[layer])
var portal := smoothstep(1.75,2.75,elapsed)*(1.0-smoothstep(3.18,3.6,elapsed))
var gate := Vector2(size.x*0.5,size.y*0.24)
if portal > 0.001:
draw_set_transform(gate,0,Vector2(1,0.24))
for halo in range(8,0,-1): draw_circle(Vector2.ZERO,(100.0+halo*6)*portal,Color(0.15,0.65,1.0,0.014))
draw_circle(Vector2.ZERO,104*portal,Color(0.01,0.035,0.065,0.95))
for ring in 3:
draw_arc(Vector2.ZERO,(102+ring*5)*portal,elapsed*(2+ring),elapsed*(2+ring)+TAU*0.91,96,Color(0.4+ring*0.2,0.8+ring*0.07,1.0,0.8),2.0,true)
draw_set_transform(Vector2.ZERO)
if elapsed > 3.05:
var flare := exp(-pow((elapsed-3.16)/0.12,2.0))
for layer in range(6,0,-1):
draw_line(gate-Vector2(size.x*0.45,0),gate+Vector2(size.x*0.45,0),Color(0.3,0.8,1.0,flare*0.07),float(layer*4),true)
var ring_time := maxf(0.0,elapsed-3.15)
draw_arc(gate,20.0+ring_time*650.0,0,TAU,96,Color(0.4,0.85,1.0,maxf(0.0,0.65-ring_time)),2.0,true)
draw_line(gate,gate+Vector2(0,-size.y),Color(0.8,0.98,1.0,flare),4.0+flare*24.0,true)
func _play_audio() -> void:
var rate := 22050
var data := PackedByteArray()
data.resize(int(DURATION*rate)*2)
var rng := RandomNumberGenerator.new()
rng.seed = 73902
var phase := 0.0
var noise := 0.0
for sample in int(DURATION*rate):
var t := float(sample)/rate
var rise := smoothstep(0.0,3.1,t)
phase += TAU*(38.0+rise*140.0)/rate
noise = lerpf(noise,rng.randf_range(-1,1),0.12+rise*0.2)
var envelope := smoothstep(0,0.3,t)*(1.0-smoothstep(3.15,3.8,t))
var rush := exp(-pow((t-3.14)/0.16,2.0))
var value := (sin(phase)*0.13+sin(phase*1.51)*0.05+noise*(0.1+rise*0.25))*envelope+noise*rush*0.55
data.encode_s16(sample*2,int(clampf(value,-0.9,0.9)*32767))
var stream := AudioStreamWAV.new()
stream.format = AudioStreamWAV.FORMAT_16_BITS
stream.mix_rate = rate
stream.data = data
var audio := AudioStreamPlayer.new()
audio.stream = stream
audio.volume_db = -9.0
if AudioServer.get_bus_index("Effects") >= 0: audio.bus = &"Effects"
add_child(audio)
audio.play()