Optimize simulation system a bit

main
Elijah Voigt 8 hours ago
parent e89886382d
commit 397b60b18c

@ -1,15 +1,14 @@
// TODO: // TODO:
// * Volume slider // * Volume slider
// * Invert mute/unmute icons
// * Only move camera when cells move out of view // * Only move camera when cells move out of view
// * "Follow" enhancement: Zoom in/out
// * optimize simulation_step
// * Stop creating cells when I didn't mean to (clicking UI, click + dragging) // * Stop creating cells when I didn't mean to (clicking UI, click + dragging)
// * Keep some controls open when main ui panel is closed // * Keep some controls open when main ui panel is closed
// * Exclude power button from web build
// * Show shadow of piece (same tile, just with alpha transparency) // * Show shadow of piece (same tile, just with alpha transparency)
// * Dark mode // * Dark mode
// * Make click and drag feel better // * Make click and drag feel better
// * Add arrow keys to move around // * Add arrow keys to move around
// * "Follow" enhancement: Zoom in/out
#![allow(clippy::complexity)] #![allow(clippy::complexity)]
// Only because of FromTemplat macros unfortunately... // Only because of FromTemplat macros unfortunately...
#![allow(dead_code)] #![allow(dead_code)]
@ -821,61 +820,45 @@ enum SimulationPlayback {
fn simulation_step( fn simulation_step(
q: Query<(Entity, &Coordinates), With<Cell>>, q: Query<(Entity, &Coordinates), With<Cell>>,
mut writer: MessageWriter<Lifecycle>, mut writer: MessageWriter<Lifecycle>,
mut alive: Local<HashMap<Coordinates, Entity>>,
mut candidates: Local<HashSet<Coordinates>>,
) { ) {
fn is_cell_alive( let living_neighbors = |a: &HashMap<Coordinates, Entity>, c: &Coordinates| -> usize {
coordinates: &Coordinates,
query: &Query<(Entity, &Coordinates), With<Cell>>,
) -> bool {
query.iter().any(|(_e, c)| *c == *coordinates)
}
fn living_neighbors(
c: &Coordinates,
query: &Query<(Entity, &Coordinates), With<Cell>>,
) -> usize {
c.neighbors() c.neighbors()
.filter(|neighbor| { .filter(|neighbor| {
query a.contains_key(neighbor)
.iter()
.any(|(_e, coordinates)| *neighbor == *coordinates)
}) })
.count() .count()
} };
fn cell_entity( // Reset alive cell cache
coordinates: &Coordinates, *alive = q.iter().map(|(e, c)| (c.clone(), e)).collect();
query: Query<(Entity, &Coordinates), With<Cell>>,
) -> Option<Entity> {
query
.iter()
.find_map(|(e, c)| (*c == *coordinates).then_some(e))
}
// Collect list of candidate positions... // Clear candidate coordinates
let mut coordinates: HashSet<Coordinates> = HashSet::new(); candidates.clear();
// Put all dead cells neighboring living cells into the coordinates hashset // Put all dead cells neighboring living cells into the coordinates hashset
// Each living cell // Each living cell
q.iter().for_each(|(_e, c)| { q.iter().for_each(|(_e, c)| {
coordinates.insert(c.clone()); candidates.insert(c.clone());
// Iterator over neighbor positions // Iterator over neighbor positions
// Filter to just dead neighbors // Filter to just dead neighbors
c.neighbors() c.neighbors()
.filter(|c| !is_cell_alive(c, &q)) .filter(|c| !alive.contains_key(c))
.for_each(|c| { .for_each(|c| {
coordinates.insert(c); candidates.insert(c);
}); });
}); });
// Get Neighbor Count of living cells // Get Neighbor Count of living cells
coordinates.iter().for_each(|c| { candidates.iter().for_each(|c| {
let num_living_neighbors = living_neighbors(c, &q); let num_living_neighbors = living_neighbors(&*alive, c);
let is_living = is_cell_alive(c, &q); let is_living = alive.contains_key(c);
match num_living_neighbors { match num_living_neighbors {
..2 | 4.. => { ..2 | 4.. => {
if is_living { if is_living {
writer.write(Lifecycle::Dead(cell_entity(c, q).unwrap())); writer.write(Lifecycle::Dead(alive.get(c).cloned().unwrap()));
} }
} }
2 => debug!("continue"), 2 => debug!("continue"),

Loading…
Cancel
Save