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::(); app.add_systems(Update, on_bullet_fired_event.run_if(on_event::)); } } #[derive(Resource)] pub struct BulletResources { pub mesh: Mesh3d, pub material: MeshMaterial3d, pub collider: Collider, } fn setup_projectiles( mut commands: Commands, mut meshes: ResMut>, mut materials: ResMut>, ) { 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, bullet_resources: Res, ) { 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::>() ); }