mod worker;
use bevy::color::palettes::css;
use bevy::diagnostic::{FrameTimeDiagnosticsPlugin, LogDiagnosticsPlugin};
use bevy::prelude::*;
use bevy::window::PrimaryWindow;
use bevy_simple_compute::prelude::*;
use worker::{Boid, BoidWorker};
const NUM_BOIDS: u32 = 2_000;
fn main() {
App::new()
.add_plugins(DefaultPlugins)
.add_plugins(LogDiagnosticsPlugin::default())
.add_plugins(FrameTimeDiagnosticsPlugin::default())
.add_plugins(AppComputePlugin)
.add_plugins(AppComputeWorkerPlugin::<BoidWorker>::default())
.insert_resource(ClearColor(css::BLACK.into()))
.add_systems(Startup, setup)
.add_systems(Update, move_entities)
.run();
}
#[derive(Component)]
struct BoidEntity(pub usize);
fn setup(
mut commands: Commands,
mut meshes: ResMut<Assets<Mesh>>,
mut materials: ResMut<Assets<ColorMaterial>>,
) {
commands.spawn(Camera2d);
let boid_mesh = meshes.add(RegularPolygon::new(2., 3));
let boid_material = materials.add(Color::from(css::ANTIQUE_WHITE));
commands.spawn((
BoidEntity(0),
Mesh2d(boid_mesh.clone()),
MeshMaterial2d(materials.add(Color::from(css::ORANGE_RED))),
));
for i in 1..NUM_BOIDS {
commands.spawn((
BoidEntity(i as usize),
Mesh2d(boid_mesh.clone()),
MeshMaterial2d(boid_material.clone()),
));
}
}
fn move_entities(
worker: ResMut<AppComputeWorker<BoidWorker>>,
q_window: Query<&Window, With<PrimaryWindow>>,
mut q_boid: Query<(&mut Transform, &BoidEntity), With<BoidEntity>>,
) {
if !worker.ready() {
return;
}
let window = q_window.single().unwrap();
let boids = worker.read_vec::<Boid>("boids_dst");
q_boid
.par_iter_mut()
.for_each(|(mut transform, boid_entity)| {
let world_pos = Vec2::new(
(window.width() / 2.) * (boids[boid_entity.0].pos.x),
(window.height() / 2.) * (boids[boid_entity.0].pos.y),
);
transform.translation = world_pos.extend(0.);
transform.look_to(Vec3::Z, boids[boid_entity.0].vel.extend(0.));
});
}