1
0
Fork 0

Improve trails

This commit is contained in:
Fabio Iotti 2024-09-01 14:45:22 +02:00
parent fd16f3b9fc
commit 94994177bf
Signed by: bruce965
GPG key ID: 4EC13D9158A96B4C
14 changed files with 239 additions and 50 deletions

View file

@ -0,0 +1,105 @@
class_name LineTrail2D
extends Line2D
## Leave a trail behind this node.
@export var tracking: Node2D
## Minimum distance before adding a new point to the trail line.
## 0 = always add a new point on each frame.
@export var min_distance: float = 1.
## Maximum length of the trail before starting to trim.
## 0 = no length limit.
@export var max_length: float = 0.
## Maximum lifetime of the trail (in seconds) before starting to trim.
## 0 = no lifetime limit.
@export var max_lifetime: float = 3.
# Each index represents the remaining time in seconds before each point is
# removed from the line, starting to count after the previous point is removed.
# As an example: [1, 2, 2] means that the first point will be removed in 1
# second; the second point 2 seconds after the first (so 3 seconds from now);
# and the third point 2 seconds after the second (so 5 seconds from now).
var _points_life := PackedFloat32Array()
func _ready() -> void:
clear_points()
func _process(delta: float) -> void:
global_transform = Transform2D.IDENTITY
var new_position := tracking.global_position
# Add new points.
var maybe_exceeds_max_length := false
if _points_life.size() == 0:
_add_point(new_position)
else:
var last_point := get_point_position(_points_life.size() - 1)
var distance_sqr := (new_position - last_point).length_squared()
if distance_sqr >= min_distance * min_distance:
_add_point(new_position)
maybe_exceeds_max_length = true
# Reduce life and remove expired points.
var remove_count := 0
if max_lifetime != 0.:
_decrease_life(delta)
remove_count += _count_expired_points(remove_count)
# Check if line length exceeds max length.
if maybe_exceeds_max_length and max_length != 0.:
remove_count += _count_overlength_points(remove_count)
# Remove expired or overlength points.
if remove_count > 0:
_remove_oldest_points(remove_count)
func _add_point(point_position: Vector2) -> void:
add_point(point_position)
var last_point_points_life := 0.
for time in _points_life:
last_point_points_life += time
_points_life.append(max_lifetime - last_point_points_life)
func _remove_oldest_points(remove_count: int) -> void:
if remove_count > 0:
points = points.slice(remove_count)
_points_life = _points_life.slice(remove_count)
func _decrease_life(delta: float, start_at := 0) -> void:
var i := start_at
while _points_life.size() > i and delta > 0.:
var sub = minf(delta, _points_life[i])
_points_life[i] -= sub
delta -= sub
i += 1
func _count_expired_points(start_at := 0) -> int:
var i := start_at
while i < _points_life.size() and _points_life[i] <= 0.:
i += 1
return i - start_at
func _count_overlength_points(start_at := 0) -> int:
var length := 0.
var all_points := points
var previous_point := all_points[start_at]
for i in range(start_at + 1, all_points.size()):
var point := all_points[i]
length += (point - previous_point).length()
previous_point = point
var overlength_count := 0
while length > max_length and overlength_count < all_points.size() - 1:
var removed_point = all_points[overlength_count]
var next_point = all_points[overlength_count + 1]
length -= (removed_point - next_point).length()
overlength_count += 1
return overlength_count

View file

@ -1,12 +0,0 @@
shader_type canvas_item;
float rand(vec2 co){
return fract(sin(dot(co, vec2(12.9898, 78.233))) * 43758.5453);
}
void fragment() {
if (rand(SCREEN_UV) > COLOR.a - abs(UV.y * 2. - 1.))
discard;
COLOR = vec4(1., 1., 1., COLOR.a);
}

View file

@ -1,22 +0,0 @@
[gd_scene load_steps=5 format=3 uid="uid://ctybb4niolni3"]
[ext_resource type="Shader" path="res://scenes/ships_fleet/fading_trail.gdshader" id="1_tajfm"]
[sub_resource type="ShaderMaterial" id="ShaderMaterial_ys3et"]
shader = ExtResource("1_tajfm")
[sub_resource type="PlaceholderTexture2D" id="PlaceholderTexture2D_gcgjo"]
size = Vector2(12, 4)
[sub_resource type="Gradient" id="Gradient_6a1ig"]
colors = PackedColorArray(1, 1, 1, 1, 1, 1, 1, 0)
[node name="Ship" type="CPUParticles2D"]
material = SubResource("ShaderMaterial_ys3et")
amount = 100
lifetime = 3.0
lifetime_randomness = 0.3
texture = SubResource("PlaceholderTexture2D_gcgjo")
particle_flag_align_y = true
gravity = Vector2(0, 0)
color_ramp = SubResource("Gradient_6a1ig")

View file

@ -0,0 +1,10 @@
class_name Ship
extends Node2D
@export var color: Color :
set(value):
color = value
_update_color(color)
func _update_color(ship_color: Color) -> void:
%LineTrail.material.set_shader_parameter('color', ship_color)

Binary file not shown.

After

Width:  |  Height:  |  Size: 117 B

View file

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://b37ho2wwsaku2"
path="res://.godot/imported/ship.png-078d321c402a0152c6a650c49954073a.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://scenes/ships_fleet/ship/ship.png"
dest_files=["res://.godot/imported/ship.png-078d321c402a0152c6a650c49954073a.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=8
detect_3d/compress_to=1

View file

@ -0,0 +1,31 @@
[gd_scene load_steps=7 format=3 uid="uid://ctybb4niolni3"]
[ext_resource type="Script" path="res://scenes/ships_fleet/ship/ship.gd" id="1_h6q7s"]
[ext_resource type="Shader" path="res://scenes/ships_fleet/ship/trail.gdshader" id="2_vgm83"]
[ext_resource type="Texture2D" uid="uid://dp0ugxgq8stt1" path="res://scenes/ships_fleet/ship/ship_trail.png" id="3_hk6vp"]
[ext_resource type="Script" path="res://scenes/line_trail/line_trail_2d.gd" id="4_wo8wd"]
[ext_resource type="Texture2D" uid="uid://b37ho2wwsaku2" path="res://scenes/ships_fleet/ship/ship.png" id="5_fxsfx"]
[sub_resource type="ShaderMaterial" id="ShaderMaterial_bt3sr"]
resource_local_to_scene = true
shader = ExtResource("2_vgm83")
shader_parameter/color = Color(1, 0, 1, 1)
[node name="Ship" type="Node2D"]
script = ExtResource("1_h6q7s")
[node name="LineTrail" type="Line2D" parent="." node_paths=PackedStringArray("tracking")]
unique_name_in_owner = true
material = SubResource("ShaderMaterial_bt3sr")
points = PackedVector2Array(-128, 0, 0, 0)
width = 15.0
texture = ExtResource("3_hk6vp")
texture_mode = 2
script = ExtResource("4_wo8wd")
tracking = NodePath("..")
max_length = 128.0
[node name="Sprite" type="Sprite2D" parent="."]
texture_repeat = 1
texture = ExtResource("5_fxsfx")
offset = Vector2(1.5, 0.5)

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

View file

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://dp0ugxgq8stt1"
path="res://.godot/imported/ship_trail.png-f2252d97e1401056e3019455c7966396.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://scenes/ships_fleet/ship/ship_trail.png"
dest_files=["res://.godot/imported/ship_trail.png-f2252d97e1401056e3019455c7966396.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

View file

@ -0,0 +1,8 @@
shader_type canvas_item;
render_mode blend_add;
uniform vec3 color: source_color = vec3(1., 0., 1.);
void fragment() {
COLOR = vec4(COLOR.r * color + COLOR.ggg, 1.);
}

View file

@ -1,9 +1,9 @@
extends Node2D extends Node2D
class_name ShipsFleet class_name ShipsFleet
@export var departed_at: float # Time.get_ticks_msec() @export var departed_at: int # Time.get_ticks_msec()
@export var arrives_at: float # Time.get_ticks_msec() @export var arrives_at: int # Time.get_ticks_msec()
@export var from: Vector2 @export var from: Vector2
@ -14,7 +14,7 @@ class_name ShipsFleet
@export var count: int : @export var count: int :
set(value): set(value):
count = value count = value
_update__instances_count() _update_instances_count()
@export var trail: Trail @export var trail: Trail
@ -36,14 +36,16 @@ var _instances: Array[Node2D] = []
@export var ship_template: PackedScene @export var ship_template: PackedScene
func _update__instances_count() -> void: func _update_instances_count() -> void:
var diff = count - _instances.size() var diff = count - _instances.size()
for i in range(diff): for i in range(diff):
var j = float(1 + _instances.size()) var j = float(1 + _instances.size())
var ship := ship_template.instantiate() var ship: Ship = ship_template.instantiate()
ship.color = player.color
add_child(ship) add_child(ship)
ship.position = Vector2.from_angle(j) * j * 2. ship.position = Vector2.from_angle(j) * j * 2.
ship.look_at(to - from)
_instances.push_back(ship) _instances.push_back(ship)
for i in range(-diff): for i in range(-diff):
@ -59,10 +61,9 @@ func _update_position(tick: int) -> void:
position = lerp(from, to, smoothstep(0., 1., progress)) position = lerp(from, to, smoothstep(0., 1., progress))
if tick >= arrives_at: if tick >= arrives_at:
_arrived = true _arrived = true
trail.show = false trail.show_trail = false
for ship in _instances: # TODO: fade out ships.
ship.emitting = false
await get_tree().create_timer(5.).timeout await get_tree().create_timer(5.).timeout
queue_free() queue_free()

View file

@ -1,7 +1,7 @@
[gd_scene load_steps=3 format=3 uid="uid://cpffyaoh8x5bp"] [gd_scene load_steps=3 format=3 uid="uid://cpffyaoh8x5bp"]
[ext_resource type="Script" path="res://scenes/ships_fleet/ships_fleet.gd" id="1_qfy0m"] [ext_resource type="Script" path="res://scenes/ships_fleet/ships_fleet.gd" id="1_qfy0m"]
[ext_resource type="PackedScene" uid="uid://ctybb4niolni3" path="res://scenes/ships_fleet/ship.tscn" id="2_6eafk"] [ext_resource type="PackedScene" uid="uid://ctybb4niolni3" path="res://scenes/ships_fleet/ship/ship.tscn" id="2_6eafk"]
[node name="ShipsFleet" type="Node2D"] [node name="ShipsFleet" type="Node2D"]
script = ExtResource("1_qfy0m") script = ExtResource("1_qfy0m")

View file

@ -8,9 +8,9 @@ static var _inv_texture_width := NAN
color = value color = value
_update_color(color) _update_color(color)
@export var show: bool = true : @export var show_trail: bool = true :
set(value): set(value):
show = value show_trail = value
visible = true visible = true
@export var auto_free: bool @export var auto_free: bool
@ -36,13 +36,13 @@ func _update_transform(start: Vector2, end: Vector2) -> void:
scale = Vector2((end - start).length() * _inv_texture_width, 1.) scale = Vector2((end - start).length() * _inv_texture_width, 1.)
func _update_color(color: Color) -> void: func _update_color(trail_color: Color) -> void:
var c := Color(color.r, color.g, color.b, color.a * _opacity) var c := Color(trail_color.r, trail_color.g, trail_color.b, trail_color.a * _opacity)
material.set_shader_parameter('color', c) material.set_shader_parameter('color', c)
func _process(delta: float) -> void: func _process(delta: float) -> void:
var prev_opacity := _opacity var prev_opacity := _opacity
_opacity = Utils.damp(_opacity, 1. if show else 0., 1e-4, delta) _opacity = Utils.damp(_opacity, 1. if show_trail else 0., 1e-4, delta)
if _opacity != prev_opacity: if _opacity != prev_opacity:
if _opacity < .01: if _opacity < .01:
_opacity = 0. _opacity = 0.

View file

@ -72,8 +72,8 @@ func _on_planet_pointer_exited(planet: ControlPlanet) -> void:
#region Trail #region Trail
func _update_trail(delta: float, snap_position: bool) -> void: func _update_trail(delta: float, snap_position: bool) -> void:
_trail.show = _dragging_from_planet and _selected_planet != null and _selected_planet.player is LocalPlayer _trail.show_trail = _dragging_from_planet and _selected_planet != null and _selected_planet.player is LocalPlayer
if _trail.show: if _trail.show_trail:
_trail.color = _selected_planet.player.color _trail.color = _selected_planet.player.color
var target_position = _last_cursor_position if _pointed_planet == null else _pointed_planet.global_position var target_position = _last_cursor_position if _pointed_planet == null else _pointed_planet.global_position
_trail.start_position = _selected_planet.global_position _trail.start_position = _selected_planet.global_position