From 94994177bfbbc2fc4b6c2ea220db78d38651e3be Mon Sep 17 00:00:00 2001 From: Fabio Iotti Date: Sun, 1 Sep 2024 14:45:22 +0200 Subject: [PATCH] Improve trails --- scenes/line_trail/line_trail_2d.gd | 105 ++++++++++++++++++ scenes/ships_fleet/fading_trail.gdshader | 12 -- scenes/ships_fleet/ship.tscn | 22 ---- scenes/ships_fleet/ship/ship.gd | 10 ++ scenes/ships_fleet/ship/ship.png | Bin 0 -> 117 bytes scenes/ships_fleet/ship/ship.png.import | 34 ++++++ scenes/ships_fleet/ship/ship.tscn | 31 ++++++ scenes/ships_fleet/ship/ship_trail.png | Bin 0 -> 2844 bytes scenes/ships_fleet/ship/ship_trail.png.import | 34 ++++++ scenes/ships_fleet/ship/trail.gdshader | 8 ++ scenes/ships_fleet/ships_fleet.gd | 17 +-- scenes/ships_fleet/ships_fleet.tscn | 2 +- scenes/trail/trail.gd | 10 +- scripts/ui/planets_ui.gd | 4 +- 14 files changed, 239 insertions(+), 50 deletions(-) create mode 100644 scenes/line_trail/line_trail_2d.gd delete mode 100644 scenes/ships_fleet/fading_trail.gdshader delete mode 100644 scenes/ships_fleet/ship.tscn create mode 100644 scenes/ships_fleet/ship/ship.gd create mode 100644 scenes/ships_fleet/ship/ship.png create mode 100644 scenes/ships_fleet/ship/ship.png.import create mode 100644 scenes/ships_fleet/ship/ship.tscn create mode 100644 scenes/ships_fleet/ship/ship_trail.png create mode 100644 scenes/ships_fleet/ship/ship_trail.png.import create mode 100644 scenes/ships_fleet/ship/trail.gdshader diff --git a/scenes/line_trail/line_trail_2d.gd b/scenes/line_trail/line_trail_2d.gd new file mode 100644 index 0000000..337c16a --- /dev/null +++ b/scenes/line_trail/line_trail_2d.gd @@ -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 diff --git a/scenes/ships_fleet/fading_trail.gdshader b/scenes/ships_fleet/fading_trail.gdshader deleted file mode 100644 index a45daec..0000000 --- a/scenes/ships_fleet/fading_trail.gdshader +++ /dev/null @@ -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); -} diff --git a/scenes/ships_fleet/ship.tscn b/scenes/ships_fleet/ship.tscn deleted file mode 100644 index e5b1852..0000000 --- a/scenes/ships_fleet/ship.tscn +++ /dev/null @@ -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") diff --git a/scenes/ships_fleet/ship/ship.gd b/scenes/ships_fleet/ship/ship.gd new file mode 100644 index 0000000..f35601e --- /dev/null +++ b/scenes/ships_fleet/ship/ship.gd @@ -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) diff --git a/scenes/ships_fleet/ship/ship.png b/scenes/ships_fleet/ship/ship.png new file mode 100644 index 0000000000000000000000000000000000000000..ca298e17b4e8a292178abc8622113b317f3a57d3 GIT binary patch literal 117 zcmeAS@N?(olHy`uVBq!ia0vp^93afW1|*O0@9PFqHl8kyArhC96BO9~{QtlI;eR0b z_y7O>2Jgnh^(;TW|Nmdlp40X1zdQ2|pCA1>Ou|#zI8BV44luH~m OISihzelF{r5}E)IkSodn literal 0 HcmV?d00001 diff --git a/scenes/ships_fleet/ship/ship.png.import b/scenes/ships_fleet/ship/ship.png.import new file mode 100644 index 0000000..81e3f13 --- /dev/null +++ b/scenes/ships_fleet/ship/ship.png.import @@ -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 diff --git a/scenes/ships_fleet/ship/ship.tscn b/scenes/ships_fleet/ship/ship.tscn new file mode 100644 index 0000000..a6552bc --- /dev/null +++ b/scenes/ships_fleet/ship/ship.tscn @@ -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) diff --git a/scenes/ships_fleet/ship/ship_trail.png b/scenes/ships_fleet/ship/ship_trail.png new file mode 100644 index 0000000000000000000000000000000000000000..1d6dab59aa2a11cc26eea84814170733dcf12733 GIT binary patch literal 2844 zcmV+%3*+>OP)RR{3T_qUF{qCr_w*B!0b_IR`1OcJ-5HWrK`D;}W;Ehs3XD!@`wGOhBkm7-)@ zBD5-@nTRT^gjH=sgjNuV2}IzB3N|8$eF$X?5%NP(H&TS6Hk56ZLO_UY3Tm9h@$xXU zvttiy?EHa5bRLeb&OQI`nR|ct-tW0_xxZX8KX0jh>72{8?>(vYevIV(mDNq~D)<+$ z0nY9;owEZS0mV>zkmeFNmoE8E>AoGy@07=PW7KbLq?Z!s+le;svbD?g*rneG&wxJ$ z--2D|P5mpto&mahhxRZXy=d>S<1G= z?E~N-I0PvV=pGu9IWWL456DkkRK6>77;R-Bgv^5L1UE}x>o#zkV4slg6l@4?-KOcbXTVV*$9uhSqSqU8 z417>f64Zs%*=l#Aatu-v92}rOIl$kd@YSB3?IS?BHzCrG>gaZay=-^msr6#p*6mKL zy+SJ67JLdE8M4`pq$+rwe#XWI_*DkleVQHk{t41;U)}oz1eJkNS9%sM^s*v&0X7%C z!E2|z#LH{Gb-@D2=b^X-@`q470mVN;_CxX0P&9pjJm6aLNfnB(nI!+}da~qNGUgEZ zvm7G3+(1@Mle4DDqYjaEhe<<){86UKIfwA`_LDzxguJdoW=!C;Y0}AI@(B}IFh$y~ zCFfj&pHd-lZKi7~2Qz*NUj4Gq1Ozts`$6QAiGKq!>QuQ&+JAgSQvfv1g`Y@Tujkv=EnNvYi z32UawoN-iD$(<(f<#gkm!j&pGszi>se#@gd*OR6R?8-RVP{CdkIOYhMGlA}SpHlA2 z*D^tlm_nB`t4wB<(XbC=rpTxXRMX{8lBO{k8QQDvaC>BPXC(f{~5Cg?)*I|d!E#?NKWS4q>`J+f<>~H7fB^w zC5z_BdY&Qme2!E-N7i$K)Xb9Qyg)WI$xN2WMm|km(kAun!n(UiN0U^tK<4u>Su+b+ zA`Nq7*`Jg3v`EFxSjiG;tC2HVLe(sp^Os~bvt-nM)bcQCX^>UBF_)hqHTRH~8LXyB z+7?Jv4eiX5wt2E{2IZ7U!!aybAWLbG4SP{DPUdqAZ8K!a?~qY5sHaI<_Ti*S(#{+y zsbQ%n{{lLxk|hmP)JP*UXsMGWRkC3gW&b|VTO&*AsH>B)G*DM2^Xh2l7Sgh{r%JWA z>>H$&Dpu4<3yis%R863joBO$<-e1_|%=8yhOU-8H{fLpxvJK~cu=M)8d~p7ibvbVV z?0y7xufi2yfGdu{uK(OVEsb>B&*W-GUKpt|GBffJBWFgQqi7f3WTaYrlcH8UO;Ilj ziqpko6f?#16rJJ;idrfZCv%iywz!9MvO&>KnWB*=NT+B}w5*YZqD9emnqodrkY+lh znGK41?kCMGkVa0Edd4WaU)*vkq@0tap+%~BilW|KDmF+poxWDt7#YhfDQlCljFD>NobRD7D&@FSpxC*&XnRL=1SD7WZr;3gSxl5IFGEWYfBe!exr}A+P(orXy>Gqb)uIkw@lg-TFDphi$GP$q2n3YI7XUNM&amX2R z+&Z~S2W@Mloice@8CN+?j(Z7rStgstNIO-0LzT2OwtTtW82N^h_)`^m_4m)tDoX34 zqZcfI*YAUK`{3;N;f-gu!H zOVKV4lI2`U(avpTF-IwuvqqZvH`2~AikXy2Jui}#+(}VSY3t&c#k5E*Pm$H`g?%*G^88CzbG|)8wJdY>iagGC8G=C(|GgStd)GSjsFpWf4zmkVn$}X0Kz(DtT57 z-^na_(itpS-rBnyPGgIoQ%>TM?$^4v12o7ft9T_d=(dJg!O}Qp3DO@^Lk^RLHZb;YoG!xRTAydFwWR@R`?Fy!qYv zS6Xr&3Y4=u+yQri#|$P_M&Bqv~mL$jgtk}V!F zo!5T%LKyV7hESki8A5@6wTA+QJjewo(3gf#pkEt6fqp~qKlz zQJ{N=P@qo<>Eb_4!7mS>K#d-rV*mxx@0}gMg=Ty5+nCQV3Ur&0nH^CeTR2aTGc$k! z&76k|37&cd=2{2z-!Pq;J*MchO9MVS9+lU0000 void: +func _update_instances_count() -> void: var diff = count - _instances.size() for i in range(diff): var j = float(1 + _instances.size()) - var ship := ship_template.instantiate() + var ship: Ship = ship_template.instantiate() + ship.color = player.color add_child(ship) ship.position = Vector2.from_angle(j) * j * 2. + ship.look_at(to - from) _instances.push_back(ship) for i in range(-diff): @@ -59,10 +61,9 @@ func _update_position(tick: int) -> void: position = lerp(from, to, smoothstep(0., 1., progress)) if tick >= arrives_at: _arrived = true - trail.show = false + trail.show_trail = false - for ship in _instances: - ship.emitting = false + # TODO: fade out ships. await get_tree().create_timer(5.).timeout queue_free() diff --git a/scenes/ships_fleet/ships_fleet.tscn b/scenes/ships_fleet/ships_fleet.tscn index d99bda5..63879b1 100644 --- a/scenes/ships_fleet/ships_fleet.tscn +++ b/scenes/ships_fleet/ships_fleet.tscn @@ -1,7 +1,7 @@ [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="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"] script = ExtResource("1_qfy0m") diff --git a/scenes/trail/trail.gd b/scenes/trail/trail.gd index 088fa80..42574ac 100644 --- a/scenes/trail/trail.gd +++ b/scenes/trail/trail.gd @@ -8,9 +8,9 @@ static var _inv_texture_width := NAN color = value _update_color(color) -@export var show: bool = true : +@export var show_trail: bool = true : set(value): - show = value + show_trail = value visible = true @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.) -func _update_color(color: Color) -> void: - var c := Color(color.r, color.g, color.b, color.a * _opacity) +func _update_color(trail_color: Color) -> void: + var c := Color(trail_color.r, trail_color.g, trail_color.b, trail_color.a * _opacity) material.set_shader_parameter('color', c) func _process(delta: float) -> void: 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 < .01: _opacity = 0. diff --git a/scripts/ui/planets_ui.gd b/scripts/ui/planets_ui.gd index df231df..e0d92a4 100644 --- a/scripts/ui/planets_ui.gd +++ b/scripts/ui/planets_ui.gd @@ -72,8 +72,8 @@ func _on_planet_pointer_exited(planet: ControlPlanet) -> void: #region Trail func _update_trail(delta: float, snap_position: bool) -> void: - _trail.show = _dragging_from_planet and _selected_planet != null and _selected_planet.player is LocalPlayer - if _trail.show: + _trail.show_trail = _dragging_from_planet and _selected_planet != null and _selected_planet.player is LocalPlayer + if _trail.show_trail: _trail.color = _selected_planet.player.color var target_position = _last_cursor_position if _pointed_planet == null else _pointed_planet.global_position _trail.start_position = _selected_planet.global_position