Optimize simulation system a bit

main
Elijah Voigt 4 hours ago
parent e89886382d
commit 397b60b18c

@ -1,15 +1,14 @@
// TODO:
// * Volume slider
// * Invert mute/unmute icons
// * 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)
// * 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)
// * Dark mode
// * Make click and drag feel better
// * Add arrow keys to move around
// * "Follow" enhancement: Zoom in/out
#![allow(clippy::complexity)]
// Only because of FromTemplat macros unfortunately...
#![allow(dead_code)]
@ -821,61 +820,45 @@ enum SimulationPlayback {
fn simulation_step(
q: Query<(Entity, &Coordinates), With<Cell>>,
mut writer: MessageWriter<Lifecycle>,
mut alive: Local<HashMap<Coordinates, Entity>>,
mut candidates: Local<HashSet<Coordinates>>,
) {
fn is_cell_alive(
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 {
let living_neighbors = |a: &HashMap<Coordinates, Entity>, c: &Coordinates| -> usize {
c.neighbors()
.filter(|neighbor| {
query
.iter()
.any(|(_e, coordinates)| *neighbor == *coordinates)
a.contains_key(neighbor)
})
.count()
}
};
fn cell_entity(
coordinates: &Coordinates,
query: Query<(Entity, &Coordinates), With<Cell>>,
) -> Option<Entity> {
query
.iter()
.find_map(|(e, c)| (*c == *coordinates).then_some(e))
}
// Reset alive cell cache
*alive = q.iter().map(|(e, c)| (c.clone(), e)).collect();
// Collect list of candidate positions...
let mut coordinates: HashSet<Coordinates> = HashSet::new();
// Clear candidate coordinates
candidates.clear();
// Put all dead cells neighboring living cells into the coordinates hashset
// Each living cell
q.iter().for_each(|(_e, c)| {
coordinates.insert(c.clone());
candidates.insert(c.clone());
// Iterator over neighbor positions
// Filter to just dead neighbors
c.neighbors()
.filter(|c| !is_cell_alive(c, &q))
.filter(|c| !alive.contains_key(c))
.for_each(|c| {
coordinates.insert(c);
candidates.insert(c);
});
});
// Get Neighbor Count of living cells
coordinates.iter().for_each(|c| {
let num_living_neighbors = living_neighbors(c, &q);
let is_living = is_cell_alive(c, &q);
candidates.iter().for_each(|c| {
let num_living_neighbors = living_neighbors(&*alive, c);
let is_living = alive.contains_key(c);
match num_living_neighbors {
..2 | 4.. => {
if is_living {
writer.write(Lifecycle::Dead(cell_entity(c, q).unwrap()));
writer.write(Lifecycle::Dead(alive.get(c).cloned().unwrap()));
}
}
2 => debug!("continue"),

Loading…
Cancel
Save