rust-sandbox / rust /src /grid.rs
DSDUDEd's picture
Update rust/src/grid.rs
3c3d7ad verified
Raw
History Blame Contribute Delete
4.93 kB
use crate::grain::GrainType;
use crate::utils::constants::{GAME_RESOLUTION_X, GAME_RESOLUTION_Y};
use bevy::prelude::*;
/*
🦀 Resources and Components. Learn more: https://bevy-cheatbook.github.io/programming/res.html
*/
#[derive(Resource)]
pub struct Grid {
data: [[Option<GrainType>; GAME_RESOLUTION_X]; GAME_RESOLUTION_Y],
spatial_hash: Vec<Vec<GridPosition>>, // For faster neighbor lookups
dirty_cells: Vec<GridPosition>, // Track cells that need updating
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub struct GridPosition {
pub current_x: i32,
pub current_y: i32,
pub prev_x: Option<i32>,
pub prev_y: Option<i32>,
}
impl GridPosition {
pub fn new(x: i32, y: i32) -> Self {
GridPosition {
current_x: x,
current_y: y,
prev_x: None,
prev_y: None,
}
}
pub fn is_moving(&self) -> bool {
match (self.prev_x, self.prev_y) {
(Some(prev_x), Some(prev_y)) => {
prev_x != self.current_x || prev_y != self.current_y
}
_ => false,
}
}
pub fn reset_prev(&mut self) {
self.prev_x = None;
self.prev_y = None;
}
}
impl Grid {
pub fn new() -> Grid {
let spatial_hash = vec![vec![]; (GAME_RESOLUTION_X * GAME_RESOLUTION_Y) / 64]; // Simple spatial partitioning
Grid {
data: [[None; GAME_RESOLUTION_X]; GAME_RESOLUTION_Y],
spatial_hash,
dirty_cells: Vec::new(),
}
}
pub fn get(&self, x: usize, y: usize) -> Option<GrainType> {
if x < GAME_RESOLUTION_X && y < GAME_RESOLUTION_Y {
self.data[y][x]
} else {
None
}
}
pub fn get_checked(&self, x: i32, y: i32) -> Option<GrainType> {
if x >= 0 && x < GAME_RESOLUTION_X as i32 && y >= 0 && y < GAME_RESOLUTION_Y as i32 {
self.data[y as usize][x as usize]
} else {
None
}
}
pub fn set(&mut self, x: usize, y: usize, value: GrainType) {
if x < GAME_RESOLUTION_X && y < GAME_RESOLUTION_Y {
self.data[y][x] = Some(value);
self.dirty_cells.push(GridPosition::new(x as i32, y as i32));
}
}
pub fn clear(&mut self, x: usize, y: usize) {
if x < GAME_RESOLUTION_X && y < GAME_RESOLUTION_Y {
self.data[y][x] = None;
self.dirty_cells.push(GridPosition::new(x as i32, y as i32));
}
}
pub fn swap(&mut self, x1: usize, y1: usize, x2: usize, y2: usize) {
if x1 < GAME_RESOLUTION_X && y1 < GAME_RESOLUTION_Y &&
x2 < GAME_RESOLUTION_X && y2 < GAME_RESOLUTION_Y {
self.data[y1][x1].swap(&mut self.data[y2][x2]);
self.dirty_cells.push(GridPosition::new(x1 as i32, y1 as i32));
self.dirty_cells.push(GridPosition::new(x2 as i32, y2 as i32));
}
}
pub fn get_neighbors(&self, x: i32, y: i32) -> [Option<GrainType>; 8] {
[
self.get_checked(x - 1, y - 1), self.get_checked(x, y - 1), self.get_checked(x + 1, y - 1),
self.get_checked(x - 1, y), self.get_checked(x + 1, y),
self.get_checked(x - 1, y + 1), self.get_checked(x, y + 1), self.get_checked(x + 1, y + 1),
]
}
pub fn take_dirty_cells(&mut self) -> Vec<GridPosition> {
std::mem::take(&mut self.dirty_cells)
}
}
#[derive(Component)]
pub struct GridPosition {
pub current_x: i32,
pub current_y: i32,
pub prev_x: Option<i32>,
pub prev_y: Option<i32>,
}
/*
🦀 Systems. Learn more: https://bevy-cheatbook.github.io/programming/systems.html
*/
pub fn update_grid_data(mut query: Query<(&GrainType, &mut GridPosition)>, mut grid_data: ResMut<Grid>) {
for (grain_type, mut grid_position) in query.iter_mut() {
// Clear the previous position from the grid
if let (Some(prev_x), Some(prev_y)) = (grid_position.prev_x, grid_position.prev_y) {
if prev_x >= 0 && prev_y >= 0 && prev_x < GAME_RESOLUTION_X as i32 && prev_y < GAME_RESOLUTION_Y as i32 {
grid_data.data[prev_y as usize][prev_x as usize] = None;
}
}
// Boundary checks for current positions
if grid_position.current_x >= 0
&& grid_position.current_x < GAME_RESOLUTION_X as i32
&& grid_position.current_y >= 0
&& grid_position.current_y < GAME_RESOLUTION_Y as i32
{
// Update the grid with the new position
grid_data.set(
grid_position.current_x as usize,
grid_position.current_y as usize,
*grain_type,
);
}
// Update prev for next frame
grid_position.prev_x = Some(grid_position.current_x);
grid_position.prev_y = Some(grid_position.current_y);
}
}