use crate::GameState; use bevy::prelude::*; #[derive(Component)] pub struct Trail { points: Vec, col_start: LinearRgba, col_end: LinearRgba, } impl Trail { pub fn new(points: usize, col_start: LinearRgba, col_end: LinearRgba) -> Self { Self { points: Vec::with_capacity(points), col_start, col_end, } } pub fn with_pos(self, pos: Vec3) -> Self { let mut trail = self; trail.add(pos); trail } pub fn add(&mut self, pos: Vec3) { if self.points.len() >= self.points.capacity() { self.points.pop(); } self.points.insert(0, pos); } } pub fn plugin(app: &mut App) { app.add_systems( FixedUpdate, update_trail.run_if(in_state(GameState::Playing)), ); } fn update_trail( mut query: Query<(Entity, &mut Trail, &Gizmo, &GlobalTransform)>, global_transform: Query<&GlobalTransform>, mut gizmo_assets: ResMut>, ) -> Result { for (e, mut trail, gizmo, pos) in query.iter_mut() { trail.add(pos.translation()); let parent_transform = global_transform.get(e)?; let Some(gizmo) = gizmo_assets.get_mut(gizmo.handle.id()) else { continue; }; gizmo.clear(); let lerp_denom = trail.points.len() as f32; gizmo.linestrip_gradient(trail.points.iter().enumerate().map(|(i, pos)| { ( GlobalTransform::from_translation(*pos) .reparented_to(parent_transform) .translation, trail.col_start.mix(&trail.col_end, i as f32 / lerp_denom), ) })); } Ok(()) }