bevy_fps/src/physics/projectiles.rs

88 lines
2.1 KiB
Rust

use bevy::prelude::*;
use avian3d::prelude::*;
use crate::util::ecs::PathTracer;
pub struct ProjectilesPlugin;
impl Plugin for ProjectilesPlugin
{
fn build(&self, app: &mut App)
{
app.add_systems(Startup, setup_projectiles);
app.add_event::<BulletFiredEvent>();
app.add_systems(Update, on_bullet_fired_event.run_if(on_event::<BulletFiredEvent>));
}
}
#[derive(Resource)]
pub struct BulletResources
{
pub mesh: Mesh3d,
pub material: MeshMaterial3d<StandardMaterial>,
pub collider: Collider,
}
fn setup_projectiles(
mut commands: Commands,
mut meshes: ResMut<Assets<Mesh>>,
mut materials: ResMut<Assets<StandardMaterial>>,
) {
commands.insert_resource(BulletResources {
mesh: Mesh3d(meshes.add(Sphere::new(1.0))),
material: MeshMaterial3d(materials.add(StandardMaterial {
base_color: Color::srgb(0.7, 0.1, 0.1),
..default()
})),
collider: Collider::sphere(1.0),
});
}
#[derive(Event, Copy, Clone, PartialEq, Debug)]
pub struct BulletFiredEvent
{
pub position: Vec3,
pub direction: Dir3,
pub speed: f32,
pub radius: f32,
pub density: f32,
}
#[derive(Component)]
pub struct Bullet;
fn on_bullet_fired_event(
mut commands: Commands,
mut events: EventReader<BulletFiredEvent>,
bullet_resources: Res<BulletResources>,
) {
let to_projectile = |event: &BulletFiredEvent|
{
let transform = Transform::IDENTITY
.with_translation(event.position)
.with_scale(Vec3::splat(event.radius))
.looking_to(event.direction, Vec3::Y);
(
Bullet,
bullet_resources.mesh.clone(),
bullet_resources.material.clone(),
bullet_resources.collider.clone(),
transform,
RigidBody::Dynamic,
ColliderDensity(event.density),
SpeculativeMargin(event.radius),
SweptCcd::LINEAR,
LinearVelocity(event.speed * event.direction),
PathTracer::default(),
)
};
commands.spawn_batch(events.read()
.map(to_projectile)
.collect::<Vec<_>>()
);
}