use crate::{Board, sim::board::Cell}; pub struct UpdateCtx<'a> { pub self_x: i32, pub self_y: i32, pub self_cell: Cell, pub delta_time: f32, pub seqno_parity: u8, pub board: &'a mut Board, } impl UpdateCtx<'_> { pub fn candidates_swap(&mut self, candidates: &[(i32, i32)]) -> bool { for candidate in candidates { let target = self.board.cell_at_position(candidate.0, candidate.1); if let Some(target) = target && target.material.def().density < self.self_cell.material.def().density { // swap the cells self.board .set_cell_at_position(self.self_x, self.self_y, target); self.board .set_cell_at_position(candidate.0, candidate.1, self.self_cell); return true; } } false } } // TODO: chunks pub fn sim_tick(board: &mut Board, seqno: u64, delta_time: f32) { // scan bottom to top to enable contiguous falling let seqno_parity = (seqno as u8) & 0b1; let bx = (board.size_x / 2) as i32; let by = (board.size_y / 2) as i32; for y in (-by..by + 1).rev() { // invert scan order on every other frame for col in -bx..bx + 1 { let x = if seqno_parity == 0 { col } else { -col }; let cell = board.cell_at_position(x, y); if let Some(mut cur) = cell && cur.flags & 0b1 == seqno_parity { // flip the parity bit cur.flags = cur.flags ^ 0b1; if let Some(update) = cur.material.def().sim_update { update(&mut UpdateCtx { self_x: x, self_y: y, self_cell: cur, board, delta_time, seqno_parity, }); } } } } }