🎨 Cleanup projectile trails logic

This commit is contained in:
Squinty 2024-04-25 13:48:08 +00:00 committed by anyreso
parent 85d8548688
commit ca189643b2
2 changed files with 49 additions and 48 deletions

View file

@ -23,11 +23,10 @@ radius = 0.15
script = ExtResource("1_4j1dp") script = ExtResource("1_4j1dp")
EXPLOSION = ExtResource("2_llml6") EXPLOSION = ExtResource("2_llml6")
[node name="Trail3D" type="MeshInstance3D" parent="."] [node name="ProjectileTrail" type="MeshInstance3D" parent="."]
material_override = SubResource("StandardMaterial3D_4a265") material_override = SubResource("StandardMaterial3D_4a265")
script = ExtResource("3_ygqbh") script = ExtResource("3_ygqbh")
_from_width = 0.15 _start_width = 0.15
_scale_acceleration = 0.5
_lifespan = 0.25 _lifespan = 0.25
_start_color = Color(0, 0.498039, 0.854902, 1) _start_color = Color(0, 0.498039, 0.854902, 1)
_end_color = Color(1, 1, 1, 0) _end_color = Color(1, 1, 1, 0)

View file

@ -14,16 +14,12 @@
# along with this program. If not, see <https://www.gnu.org/licenses/>. # along with this program. If not, see <https://www.gnu.org/licenses/>.
class_name Trail3D extends MeshInstance3D class_name Trail3D extends MeshInstance3D
var _points : Array = [] # 3D points of trail @export var _trail_enabled : bool = true
var _widths : Array = [] # Calculated widths of trail
var _lifespans : Array = [] # Trail point lifespans
@export var _trail_enabled : bool = true # Is trail shown? @export var _start_width : float = 0.5
@export var _end_width : float = 0.0
@export var _from_width : float = 0.5 # Starting width @export_range(0.5, 1.5) var _scaling_acceleration : float = 0.5
@export var _to_width : float = 0.0 # Ending width
@export_range(0.5, 1.5) var _scale_acceleration : float = 1.0 # Scaling speed
@export var _motion_delta : float = 0.1 # Smoothness of trail @export var _motion_delta : float = 0.1 # Smoothness of trail
@export var _lifespan : float = 1.0 # Duration of trail @export var _lifespan : float = 1.0 # Duration of trail
@ -31,64 +27,70 @@ var _lifespans : Array = [] # Trail point lifespans
@export var _start_color : Color = Color(1.0, 1.0, 1.0, 1.0) # Start color @export var _start_color : Color = Color(1.0, 1.0, 1.0, 1.0) # Start color
@export var _end_color : Color = Color(1.0, 1.0, 1.0, 1.0) # End color @export var _end_color : Color = Color(1.0, 1.0, 1.0, 1.0) # End color
var _old_pos : Vector3 # Previous pos var _previous_position : Vector3
var _points : Array
class PointData:
var position : Vector3
var width_0 : Vector3
var width_1 : Vector3
var lifespan : float = 0.0
func _append_point() -> void: func _append_point() -> void:
_points.append(get_global_transform().origin) var point_data : PointData = PointData.new()
_widths.append([ point_data.position = global_position
get_global_transform().basis.x * _from_width, point_data.width_0 = global_basis.x * _start_width
get_global_transform().basis.x * _from_width - get_global_transform().basis.x * _to_width point_data.width_1 = global_basis.x * _start_width - global_basis.x * _end_width
])
_lifespans.append(0.0)
func _remove_point(i : int) -> void: _points.append(point_data)
_points.remove_at(i)
_widths.remove_at(i)
_lifespans.remove_at(i)
func _ready() -> void: func _ready() -> void:
_old_pos = get_global_transform().origin _previous_position = global_position
mesh = ImmediateMesh.new() mesh = ImmediateMesh.new()
func _process(delta : float) -> void: func _process(delta : float) -> void:
if(_old_pos - get_global_transform().origin).length() > _motion_delta and _trail_enabled: if(_previous_position - global_position).length() > _motion_delta and _trail_enabled:
_append_point() # Create new point _append_point()
_old_pos = get_global_transform().origin # Update previous position to current position coordinates _previous_position = global_position
# Update the lifespan _update_lifespans(delta)
var p : int = 0 _render_trail()
var max_points : int = _points.size()
while p < max_points:
_lifespans[p] += delta
if _lifespans[p] > _lifespan:
_remove_point(p)
p -= 1
if (p < 0): p = 0
max_points = _points.size() # Update all lifespans and use a mark-and-sweep algorithm to remove "expired" points
p += 1 func _update_lifespans(delta : float) -> void:
var points_to_remove : Array = []
for point_data : PointData in _points:
point_data.lifespan += delta
if point_data.lifespan > _lifespan:
points_to_remove.append(point_data)
for point_data : PointData in points_to_remove:
_points.erase(point_data)
func _render_trail() -> void:
mesh.clear_surfaces() mesh.clear_surfaces()
# If less than 2 points, stop rendering trail var number_of_points : int = _points.size()
if _points.size() < 2: if number_of_points < 2:
return return
# Render new mesh for each point # Render new mesh for each point, triangle strips draw 2 triangles each 4 points
# which is perfect for a trail
mesh.surface_begin(Mesh.PRIMITIVE_TRIANGLE_STRIP) mesh.surface_begin(Mesh.PRIMITIVE_TRIANGLE_STRIP)
for i in range(_points.size()): for point_index in range(number_of_points):
var t : float = float(i) / (_points.size() - 1.0) var point_data : PointData = _points[point_index]
var curr_color : Color = _start_color.lerp(_end_color, 1 - t) var t : float = float(point_index) / (number_of_points - 1.0)
mesh.surface_set_color(curr_color) var current_color : Color = _start_color.lerp(_end_color, 1 - t)
mesh.surface_set_color(current_color)
var curr_width : Vector3 = _widths[i][0] - pow(1 - t, _scale_acceleration) * _widths[i][1] var current_width : Vector3 = point_data.width_0 - pow(1 - t, _scaling_acceleration) * point_data.width_1
var t0 : float = i / _points.size() var t0 : float = float(point_index) / float(number_of_points)
var t1 : float = t var t1 : float = t
mesh.surface_set_uv(Vector2(t0, 0)) mesh.surface_set_uv(Vector2(t0, 0))
mesh.surface_add_vertex(to_local(_points[i] + curr_width)) mesh.surface_add_vertex(to_local(point_data.position + current_width))
mesh.surface_set_uv(Vector2(t1, 1)) mesh.surface_set_uv(Vector2(t1, 1))
mesh.surface_add_vertex(to_local(_points[i] - curr_width)) mesh.surface_add_vertex(to_local(point_data.position - current_width))
mesh.surface_end() mesh.surface_end()