fix missile trails (#81)
added replicated `SpawnTrail` that acts as a marker and gets picked up by the client to create the visuals.
This commit is contained in:
@@ -5,7 +5,7 @@ use crate::{
|
||||
heads_database::HeadsDatabase,
|
||||
physics_layers::GameLayer,
|
||||
protocol::{GltfSceneRoot, PlaySound},
|
||||
utils::{global_observer, trail::Trail},
|
||||
utils::{global_observer, trail::SpawnTrail},
|
||||
};
|
||||
use avian3d::prelude::*;
|
||||
use bevy::prelude::*;
|
||||
@@ -15,7 +15,8 @@ use std::f32::consts::PI;
|
||||
const MAX_SHOT_AGES: f32 = 15.;
|
||||
const MISSLE_SPEED: f32 = 3.;
|
||||
|
||||
#[derive(Component)]
|
||||
#[derive(Component, Reflect)]
|
||||
#[reflect(Component)]
|
||||
struct MissileProjectile {
|
||||
time: f32,
|
||||
damage: u32,
|
||||
@@ -40,7 +41,6 @@ fn on_trigger_missile(
|
||||
query_transform: Query<&Transform>,
|
||||
time: Res<Time>,
|
||||
heads_db: Res<HeadsDatabase>,
|
||||
mut gizmo_assets: ResMut<Assets<GizmoAsset>>,
|
||||
) {
|
||||
let state = trigger.event().0;
|
||||
|
||||
@@ -66,6 +66,13 @@ fn on_trigger_missile(
|
||||
time: time.elapsed_secs(),
|
||||
damage: head.damage,
|
||||
},
|
||||
SpawnTrail::new(
|
||||
12,
|
||||
LinearRgba::rgb(1., 0.0, 0.),
|
||||
LinearRgba::rgb(0.9, 0.9, 0.),
|
||||
10.,
|
||||
)
|
||||
.init_with_pos(),
|
||||
Collider::capsule_endpoints(0.4, Vec3::new(0., 0., 2.), Vec3::new(0., 0., -2.)),
|
||||
CollisionLayers::new(
|
||||
LayerMask(GameLayer::Projectile.to_bits()),
|
||||
@@ -77,29 +84,11 @@ fn on_trigger_missile(
|
||||
Visibility::default(),
|
||||
transform,
|
||||
Replicated,
|
||||
children![
|
||||
(
|
||||
Transform::from_rotation(Quat::from_rotation_x(PI / 2.).inverse()),
|
||||
GltfSceneRoot::Projectile("missile".to_string()),
|
||||
Replicated,
|
||||
),
|
||||
(
|
||||
Trail::new(
|
||||
12,
|
||||
LinearRgba::rgb(1., 0.0, 0.),
|
||||
LinearRgba::rgb(0.9, 0.9, 0.)
|
||||
)
|
||||
.with_pos(transform.translation),
|
||||
Gizmo {
|
||||
handle: gizmo_assets.add(GizmoAsset::default()),
|
||||
line_config: GizmoLineConfig {
|
||||
width: 10.,
|
||||
..default()
|
||||
},
|
||||
..default()
|
||||
},
|
||||
)
|
||||
],
|
||||
children![(
|
||||
Transform::from_rotation(Quat::from_rotation_x(PI / 2.).inverse()),
|
||||
GltfSceneRoot::Projectile("missile".to_string()),
|
||||
Replicated
|
||||
)],
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ use crate::{
|
||||
animation::{AnimationController, AnimationFlags},
|
||||
heads_database::HeadsDatabase,
|
||||
loading_assets::GameAssets,
|
||||
utils::trail::Trail,
|
||||
utils::trail::SpawnTrail,
|
||||
};
|
||||
use bevy::{
|
||||
animation::RepeatAnimation, ecs::system::SystemParam, platform::collections::HashMap,
|
||||
@@ -125,7 +125,6 @@ fn find_marker_bones(
|
||||
mut commands: Commands,
|
||||
descendants: Query<&Children>,
|
||||
name: Query<&Name>,
|
||||
mut gizmo_assets: ResMut<Assets<GizmoAsset>>,
|
||||
) {
|
||||
let entity = trigger.event().entity;
|
||||
|
||||
@@ -139,21 +138,12 @@ fn find_marker_bones(
|
||||
commands.entity(child).insert(ProjectileOrigin);
|
||||
origin_found = true;
|
||||
} else if name.as_str().starts_with("Trail") {
|
||||
commands.entity(child).insert((
|
||||
Trail::new(
|
||||
20,
|
||||
LinearRgba::new(1., 1.0, 1., 0.5),
|
||||
LinearRgba::new(1., 1., 1., 0.5),
|
||||
),
|
||||
Gizmo {
|
||||
handle: gizmo_assets.add(GizmoAsset::default()),
|
||||
line_config: GizmoLineConfig {
|
||||
width: 24.,
|
||||
..default()
|
||||
},
|
||||
..default()
|
||||
},
|
||||
));
|
||||
commands.entity(child).insert((SpawnTrail::new(
|
||||
20,
|
||||
LinearRgba::new(1., 1.0, 1., 0.5),
|
||||
LinearRgba::new(1., 1., 1., 0.5),
|
||||
24.,
|
||||
),));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -19,7 +19,10 @@ use crate::{
|
||||
platforms::ActivePlatform,
|
||||
player::{Player, PlayerBodyMesh},
|
||||
tick::GameTick,
|
||||
utils::{auto_rotate::AutoRotation, billboards::Billboard, squish_animation::SquishAnimation},
|
||||
utils::{
|
||||
auto_rotate::AutoRotation, billboards::Billboard, squish_animation::SquishAnimation,
|
||||
trail::SpawnTrail,
|
||||
},
|
||||
};
|
||||
use avian3d::prelude::{
|
||||
AngularInertia, AngularVelocity, CenterOfMass, Collider, ColliderDensity, CollisionLayers,
|
||||
@@ -96,6 +99,7 @@ pub fn plugin(app: &mut App) {
|
||||
.replicate_once::<Npc>()
|
||||
.replicate::<SquishAnimation>()
|
||||
.replicate_once::<Transform>()
|
||||
.replicate_once::<SpawnTrail>()
|
||||
.replicate::<UiActiveHeads>()
|
||||
.replicate_as::<Visibility, SerVisibility>();
|
||||
|
||||
|
||||
@@ -1,7 +1,36 @@
|
||||
use crate::GameState;
|
||||
use bevy::prelude::*;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Component)]
|
||||
#[derive(Copy, Clone, Component, Reflect, Deserialize, Serialize)]
|
||||
#[reflect(Component)]
|
||||
pub struct SpawnTrail {
|
||||
pub points: usize,
|
||||
pub col_start: LinearRgba,
|
||||
pub col_end: LinearRgba,
|
||||
pub width: f32,
|
||||
pub init_pos: bool,
|
||||
}
|
||||
|
||||
impl SpawnTrail {
|
||||
pub fn new(points: usize, col_start: LinearRgba, col_end: LinearRgba, width: f32) -> Self {
|
||||
Self {
|
||||
points,
|
||||
col_start,
|
||||
col_end,
|
||||
width,
|
||||
init_pos: false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn init_with_pos(mut self) -> Self {
|
||||
self.init_pos = true;
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Component, Reflect)]
|
||||
#[reflect(Component)]
|
||||
pub struct Trail {
|
||||
points: Vec<Vec3>,
|
||||
col_start: LinearRgba,
|
||||
@@ -9,17 +38,19 @@ pub struct Trail {
|
||||
}
|
||||
|
||||
impl Trail {
|
||||
pub fn new(points: usize, col_start: LinearRgba, col_end: LinearRgba) -> Self {
|
||||
pub fn new(trail: SpawnTrail) -> Self {
|
||||
Self {
|
||||
points: Vec::with_capacity(points),
|
||||
col_start,
|
||||
col_end,
|
||||
points: Vec::with_capacity(trail.points),
|
||||
col_start: trail.col_start,
|
||||
col_end: trail.col_end,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn with_pos(self, pos: Vec3) -> Self {
|
||||
pub fn with_pos(self, pos: Option<Vec3>) -> Self {
|
||||
let mut trail = self;
|
||||
trail.add(pos);
|
||||
if let Some(pos) = pos {
|
||||
trail.add(pos);
|
||||
}
|
||||
trail
|
||||
}
|
||||
|
||||
@@ -36,6 +67,32 @@ pub fn plugin(app: &mut App) {
|
||||
FixedUpdate,
|
||||
update_trail.run_if(in_state(GameState::Playing)),
|
||||
);
|
||||
#[cfg(feature = "client")]
|
||||
app.add_systems(Update, attach_trail.run_if(in_state(GameState::Playing)));
|
||||
}
|
||||
|
||||
#[cfg(feature = "client")]
|
||||
fn attach_trail(
|
||||
mut commands: Commands,
|
||||
query: Query<(Entity, &Transform, &SpawnTrail), Added<SpawnTrail>>,
|
||||
mut gizmo_assets: ResMut<Assets<GizmoAsset>>,
|
||||
) {
|
||||
for (entity, transform, trail) in query.iter() {
|
||||
let width = trail.width;
|
||||
let init_pos = trail.init_pos.then_some(transform.translation);
|
||||
let id = commands
|
||||
.spawn((
|
||||
Trail::new(*trail).with_pos(init_pos),
|
||||
Gizmo {
|
||||
handle: gizmo_assets.add(GizmoAsset::default()),
|
||||
line_config: GizmoLineConfig { width, ..default() },
|
||||
..default()
|
||||
},
|
||||
))
|
||||
.id();
|
||||
|
||||
commands.entity(entity).add_child(id);
|
||||
}
|
||||
}
|
||||
|
||||
fn update_trail(
|
||||
|
||||
Reference in New Issue
Block a user