112 lines
4.5 KiB
GDScript
112 lines
4.5 KiB
GDScript
extends Node2D
|
|
## Ground wash stays in world space after emission, independently of the lander.
|
|
const LIMIT := 144
|
|
var source: Control
|
|
var weather: Node2D
|
|
var _rng := RandomNumberGenerator.new()
|
|
var _particles: Array[Dictionary] = []
|
|
var _soft: GradientTexture2D
|
|
var _shadow: Sprite2D
|
|
var _emission := 0.0
|
|
var _tree_timer := 0.0
|
|
var _near_trees := false
|
|
var _surface_kind := "dust"
|
|
var _ground := Color("b5a17a")
|
|
|
|
func _ready() -> void:
|
|
name = "SurfaceFlightEffects"
|
|
z_index = 21
|
|
texture_filter = CanvasItem.TEXTURE_FILTER_LINEAR
|
|
_rng.seed = source.progress.visit_seed ^ 0x44555354
|
|
_ground = (source.world.data.landscape.sand as Color).lerp(source.world.data.landscape.low,0.25)
|
|
var gradient := Gradient.new()
|
|
gradient.set_color(0,Color.WHITE)
|
|
gradient.set_color(1,Color(1,1,1,0))
|
|
_soft = GradientTexture2D.new()
|
|
_soft.gradient = gradient
|
|
_soft.width = 64
|
|
_soft.height = 64
|
|
_soft.fill = GradientTexture2D.FILL_RADIAL
|
|
_soft.fill_from = Vector2(0.5,0.5)
|
|
_soft.fill_to = Vector2(0.5,1)
|
|
_shadow = Sprite2D.new()
|
|
_shadow.name = "LanderShadow"
|
|
_shadow.texture = source.lander.texture
|
|
_shadow.scale = source.lander.scale*0.76
|
|
_shadow.z_index = -1
|
|
var material := ShaderMaterial.new()
|
|
material.shader = preload("res://resources/effects/lander_shadow.gdshader")
|
|
_shadow.material = material
|
|
add_child(_shadow)
|
|
|
|
func surface_kind(point: Vector2) -> String:
|
|
if int(source.world.data.landscape.index) == 5: return "snow"
|
|
var h: float = weather.terrain_height(point)
|
|
if h < 0.29 or (int(source.world.data.landscape.index) == 2 and h < 0.37): return "spray"
|
|
return "rock" if h > 0.64 else "dust"
|
|
|
|
func _process(delta: float) -> void:
|
|
if not is_instance_valid(source): return
|
|
visible = not source._ending
|
|
if source._ending: return
|
|
var pose: Transform2D = source.lander.global_transform
|
|
pose.origin = source._previous_position.lerp(source.lander.position,Engine.get_physics_interpolation_fraction())
|
|
var point := pose.origin
|
|
_shadow.position = point+Vector2(48,64)
|
|
_shadow.rotation = pose.get_rotation()
|
|
_shadow.visible = source.lander.visible
|
|
_tree_timer -= delta
|
|
if _tree_timer <= 0:
|
|
_tree_timer = 0.4
|
|
_near_trees = false
|
|
for tree in source.world.data.trees:
|
|
if point.distance_squared_to(tree.position) < 170*170:
|
|
_near_trees = true
|
|
break
|
|
_surface_kind = surface_kind(point)
|
|
var thrust: bool = source.engine_thrust_active()
|
|
var brake: bool = not source._dialog.visible and Input.is_action_pressed("ship_brake") and source._motion.velocity.length() > 12
|
|
var boost: bool = source._motion.boost_active and thrust
|
|
if thrust or brake:
|
|
var rate := 60.0 if boost else (26.0 if thrust else 18.0)
|
|
if _surface_kind == "rock": rate *= 0.3
|
|
_emission += delta*rate
|
|
while _emission >= 1:
|
|
_emission -= 1
|
|
if _particles.size() < LIMIT: _emit(point,pose.get_rotation(),boost)
|
|
else: _emission = 0
|
|
for index in range(_particles.size()-1,-1,-1):
|
|
var particle: Dictionary = _particles[index]
|
|
particle.age += delta
|
|
particle.position += (particle.velocity+weather.wind*0.7)*delta
|
|
particle.velocity *= exp(-delta*1.3)
|
|
if particle.age > particle.life: _particles.remove_at(index)
|
|
queue_redraw()
|
|
|
|
func _emit(point: Vector2, angle: float, boost: bool) -> void:
|
|
var kind := _surface_kind
|
|
if _near_trees and kind == "dust" and _rng.randf() < 0.20: kind = "leaf"
|
|
var nozzle := Vector2(_rng.randf_range(-29,29),_rng.randf_range(22,42)).rotated(angle)
|
|
var scatter := Vector2(_rng.randf_range(-32,32),_rng.randf_range(10,45)).rotated(angle)
|
|
_particles.append({"position":point+nozzle,"velocity":scatter+source._motion.velocity*0.1,"age":0.0,"life":_rng.randf_range(1.1,2.4),"size":_rng.randf_range(9,17)*(1.4 if boost else 1.0),"kind":kind,"angle":_rng.randf_range(-PI,PI)})
|
|
|
|
func _draw() -> void:
|
|
for particle in _particles:
|
|
var t := clampf(particle.age/particle.life,0,1)
|
|
var alpha := sin(t*PI)
|
|
var kind: String = particle.kind
|
|
var radius: float = particle.size*(1.0+t*1.9)
|
|
var color := _ground
|
|
color.a = alpha*0.14
|
|
if kind == "rock": color = Color(0.65,0.65,0.59,alpha*0.09)
|
|
if kind == "snow": color = Color(0.88,0.95,0.95,alpha*0.25)
|
|
if kind == "spray": color = Color(0.66,0.83,0.80,alpha*0.18)
|
|
if kind == "leaf":
|
|
draw_set_transform(particle.position,particle.angle+t*2,Vector2(1,0.45))
|
|
draw_circle(Vector2.ZERO,2.5,Color(0.49,0.35,0.17,alpha*0.7),true,-1,true)
|
|
draw_set_transform(Vector2.ZERO)
|
|
else:
|
|
draw_texture_rect(_soft,Rect2(particle.position-Vector2.ONE*radius,Vector2.ONE*radius*2),false,color)
|
|
if kind in ["spray","snow"]:
|
|
draw_circle(particle.position+Vector2(4,-7)*t,1.4,Color(color,alpha*0.38),true,-1,true)
|