use std::f32::consts::TAU;
use flax::{components::name, *};
use glam::{vec3, Vec3};
use itertools::Itertools;
use rand::{rngs::StdRng, Rng, SeedableRng};
use tracing::info_span;
use tracing_subscriber::{prelude::*, registry};
use tracing_tree::HierarchicalLayer;
fn main() {
registry().with(HierarchicalLayer::new(4)).init();
component! {
health: f32,
position: Vec3,
velocity: Vec3,
player: (),
}
let mut world = World::new();
Entity::builder()
.set(name(), "player".into())
.set(health(), 100.0)
.set_default(position())
.set_default(velocity())
.set_default(player())
.spawn(&mut world);
(0..10)
.map(|i| {
let theta = TAU * i as f32 / 10.0;
Entity::builder()
.set(name(), format!("enemy.{i}"))
.set(health(), 50.0)
.set(position(), vec3(5.0 * theta.cos(), 0.0, 5.0 * theta.sin()))
.set_default(velocity())
.spawn(&mut world)
})
.collect_vec();
(0..64)
.map(|i| {
let r = 2.0 + i as f32 / 10.0;
let theta = TAU * i as f32 / 10.0;
Entity::builder()
.set(name(), format!("rock.{i}"))
.set(position(), vec3(r * theta.cos(), 0.0, r * theta.sin()))
.spawn(&mut world)
})
.collect_vec();
{
let _span = info_span!("query_name").entered();
let mut query = Query::new(name());
for name in &mut query.borrow(&world) {
tracing::info!("Entity: {name:?}");
}
}
{
let _span = info_span!("query_tuple").entered();
let mut query = Query::new((name(), position(), health()));
for (name, pos, health) in &mut query.borrow(&world) {
tracing::info!("Entity: {name:?} pos: {pos}, health: {health}");
}
}
let mut rng = StdRng::seed_from_u64(42);
{
let _span = info_span!("query_mut").entered();
fn lightning_strike(world: &World, rng: &mut StdRng) {
let mut query = Query::new(health().as_mut());
for h in &mut query.borrow(world) {
*h -= rng.gen_range(10.0..20.0);
}
}
lightning_strike(&world, &mut rng);
}
{
let _span = info_span!("query_opt").entered();
let mut query = Query::new((name(), position(), health().opt()));
(&mut query.borrow(&world)).into_iter().for_each(
|(name, pos, health): (&String, &Vec3, Option<&f32>)| {
tracing::info!("Entity: {name:?} pos: {pos}, health: {health:?}");
},
);
}
{
let _span = info_span!("query_with").entered();
let mut query = Query::new((name(), health())).filter(player().with());
let mut borrow = query.borrow(&world);
if let Some((name, health)) = borrow.iter().next() {
tracing::info!("The player {name} is alive and well at {health} health");
} else {
tracing::info!("The player seems to have perished");
}
}
{
let _span = info_span!("query_without").entered();
let mut query = Query::new((name(), health())).filter(player().without());
for (name, health) in &mut query.borrow(&world) {
tracing::info!("Npc: {name} at {health} health");
}
}
{
let _span = info_span!("query_combinators").entered();
let mut query =
Query::new((name(), health().opt())).filter(player().with() | health().without());
for (name, health) in &mut query.borrow(&world) {
if let Some(health) = health {
tracing::info!("{name} at {health}");
} else {
tracing::info!("{name} (immortal)");
}
}
}
{
let _span = info_span!("query_cmp").entered();
let mut query = Query::new(name()).filter(health().without() | health().ge(35.0));
for name in &mut query.borrow(&world) {
tracing::info!("{name} is still standing strong");
}
}
}