Add basic falling sand

This commit is contained in:
Jarrod Doyle 2024-01-28 12:45:58 +00:00
parent ce4e13005f
commit 754466ea16
Signed by: Jayrude
GPG Key ID: 38B57B16E7C0ADF7
1 changed files with 86 additions and 7 deletions

View File

@ -11,14 +11,17 @@ use bevy::{
sprite::SpriteBundle,
transform::components::Transform,
};
use rand::random;
use rand::Rng;
pub struct FallingSandPlugin;
impl Plugin for FallingSandPlugin {
fn build(&self, app: &mut bevy::prelude::App) {
app.add_systems(Startup, setup);
app.add_systems(Update, update_chunk_texture_system);
app.add_systems(
Update,
(simulate_chunk_system, update_chunk_texture_system).chain(),
);
}
}
@ -40,10 +43,16 @@ fn setup(mut commands: Commands, mut images: ResMut<Assets<Image>>) {
.spawn(Chunk {
width: 256,
height: 256,
cells: vec![Elements::Air; 256 * 256],
})
.insert(SpriteBundle {
sprite: Sprite {
flip_y: true,
..default()
},
texture: image_handle,
transform: Transform::from_translation(Vec3::new(256., 0., 0.)),
transform: Transform::from_translation(Vec3::new(256., 0., 0.))
.with_scale(Vec3::new(2., 2., 0.)),
..default()
});
}
@ -52,6 +61,63 @@ fn setup(mut commands: Commands, mut images: ResMut<Assets<Image>>) {
pub struct Chunk {
width: usize,
height: usize,
cells: Vec<Elements>,
}
pub fn simulate_chunk_system(mut chunk: Query<&mut Chunk>) {
// We know for now there's only one chunk
let chunk = chunk.get_single_mut();
if chunk.is_err() {
return;
}
let mut query = chunk.unwrap();
let chunk = query.as_mut();
// Place sand
let frac = chunk.width / 2;
let x = (chunk.width - frac) / 2 + rand::thread_rng().gen_range(0..frac);
let y = chunk.height - 1;
chunk.cells[x + y * chunk.width] = Elements::Sand;
// Simulate sand
for y in 0..chunk.height {
for x in 0..chunk.width {
let index = x + y * chunk.width;
let element = chunk.cells.get(index).unwrap();
match element {
Elements::Air => {}
Elements::Sand => {
if y != 0 {
let b_index = index - chunk.width;
let bottom = chunk.cells.get(b_index).unwrap();
if *bottom == Elements::Air {
chunk.cells.swap(index, b_index);
continue;
}
if x != 0 {
let bl_index = b_index - 1;
let bottom_left = chunk.cells.get(bl_index).unwrap();
if *bottom_left == Elements::Air {
chunk.cells.swap(index, bl_index);
continue;
}
}
if x != chunk.width - 1 {
let br_index = b_index + 1;
let bottom_right = chunk.cells.get(br_index).unwrap();
if *bottom_right == Elements::Air {
chunk.cells.swap(index, br_index);
continue;
}
}
}
}
}
}
}
}
pub fn update_chunk_texture_system(
@ -68,13 +134,26 @@ pub fn update_chunk_texture_system(
if let Some(image) = images.get_mut(image_handle) {
for y in 0..chunk.height {
for x in 0..chunk.width {
// Just set each pixel to random colours for now
let mut colour = (0, 0, 0);
if let Some(element) = chunk.cells.get(x + y * chunk.width) {
match element {
Elements::Air => colour = (25, 24, 26),
Elements::Sand => colour = (255, 216, 102),
}
}
let index = (x + y * chunk.width) * 4;
image.data[index] = random::<u8>();
image.data[index + 1] = random::<u8>();
image.data[index + 2] = random::<u8>();
image.data[index] = colour.0;
image.data[index + 1] = colour.1;
image.data[index + 2] = colour.2;
image.data[index + 3] = 255;
}
}
}
}
#[derive(Debug, Clone, Copy, PartialEq)]
enum Elements {
Air,
Sand,
}