Move rules to a Resource

This commit is contained in:
Jarrod Doyle 2024-01-31 12:57:04 +00:00
parent cd0674fdff
commit af6fdb085b
Signed by: Jayrude
GPG Key ID: 38B57B16E7C0ADF7
1 changed files with 63 additions and 51 deletions

View File

@ -31,6 +31,7 @@ impl Plugin for FallingSandPlugin {
)
.chain(),
);
app.init_resource::<FallingSandRules>();
}
}
@ -67,58 +68,16 @@ pub struct Chunk {
height: usize,
cells: Vec<Element>,
dirty_rect: DirtyRect,
rules: HashMap<u32, u32>,
}
impl Chunk {
pub fn new(width: usize, height: usize) -> Self {
// Pre-computed air-sand rules
let rules = HashMap::from([
gen_rule(
(Element::Air, Element::Sand, Element::Air, Element::Air),
(Element::Air, Element::Air, Element::Air, Element::Sand),
),
gen_rule(
(Element::Air, Element::Sand, Element::Air, Element::Sand),
(Element::Air, Element::Air, Element::Sand, Element::Sand),
),
gen_rule(
(Element::Air, Element::Sand, Element::Sand, Element::Air),
(Element::Air, Element::Air, Element::Sand, Element::Sand),
),
gen_rule(
(Element::Sand, Element::Air, Element::Air, Element::Air),
(Element::Air, Element::Air, Element::Sand, Element::Air),
),
gen_rule(
(Element::Sand, Element::Air, Element::Air, Element::Sand),
(Element::Air, Element::Air, Element::Sand, Element::Sand),
),
gen_rule(
(Element::Sand, Element::Air, Element::Sand, Element::Air),
(Element::Air, Element::Air, Element::Sand, Element::Sand),
),
gen_rule(
(Element::Sand, Element::Sand, Element::Air, Element::Air),
(Element::Air, Element::Air, Element::Sand, Element::Sand),
),
gen_rule(
(Element::Sand, Element::Sand, Element::Air, Element::Sand),
(Element::Air, Element::Sand, Element::Sand, Element::Sand),
),
gen_rule(
(Element::Sand, Element::Sand, Element::Sand, Element::Air),
(Element::Sand, Element::Air, Element::Sand, Element::Sand),
),
]);
Self {
step: 0,
width,
height,
cells: vec![Element::Air; width * height],
dirty_rect: DirtyRect::default(),
rules,
}
}
@ -150,13 +109,6 @@ impl Chunk {
Some(self.cells[x + y * self.width])
}
pub fn get_rule_result(&self, input: u32) -> u32 {
match self.rules.get(&input) {
Some(&result) => result,
None => input,
}
}
}
pub fn place_sand_system(mut chunk: Query<&mut Chunk>) {
@ -173,7 +125,7 @@ pub fn place_sand_system(mut chunk: Query<&mut Chunk>) {
chunk.set_cell(x, y, Element::Sand);
}
pub fn simulate_chunk_system(mut chunk: Query<&mut Chunk>) {
pub fn simulate_chunk_system(rules: Res<FallingSandRules>, mut chunk: Query<&mut Chunk>) {
// We know for now there's only one chunk
let chunk = chunk.get_single_mut();
if chunk.is_err() {
@ -210,7 +162,7 @@ pub fn simulate_chunk_system(mut chunk: Query<&mut Chunk>) {
chunk.get_cell(x, y).unwrap_or(Element::None),
chunk.get_cell(x + 1, y).unwrap_or(Element::None),
));
let end_state = chunk.get_rule_result(start_state);
let end_state = rules.get_result(start_state);
// We only need to actually update things if the state changed
// Same ordering as above.
@ -298,3 +250,63 @@ fn gen_rule(
fn to_rule_state(input: (Element, Element, Element, Element)) -> u32 {
((input.0 as u32) << 24) + ((input.1 as u32) << 16) + ((input.2 as u32) << 8) + input.3 as u32
}
#[derive(Resource)]
pub struct FallingSandRules {
rules: HashMap<u32, u32>,
}
impl Default for FallingSandRules {
fn default() -> Self {
// Pre-computed air-sand rules
Self {
rules: HashMap::from([
gen_rule(
(Element::Air, Element::Sand, Element::Air, Element::Air),
(Element::Air, Element::Air, Element::Air, Element::Sand),
),
gen_rule(
(Element::Air, Element::Sand, Element::Air, Element::Sand),
(Element::Air, Element::Air, Element::Sand, Element::Sand),
),
gen_rule(
(Element::Air, Element::Sand, Element::Sand, Element::Air),
(Element::Air, Element::Air, Element::Sand, Element::Sand),
),
gen_rule(
(Element::Sand, Element::Air, Element::Air, Element::Air),
(Element::Air, Element::Air, Element::Sand, Element::Air),
),
gen_rule(
(Element::Sand, Element::Air, Element::Air, Element::Sand),
(Element::Air, Element::Air, Element::Sand, Element::Sand),
),
gen_rule(
(Element::Sand, Element::Air, Element::Sand, Element::Air),
(Element::Air, Element::Air, Element::Sand, Element::Sand),
),
gen_rule(
(Element::Sand, Element::Sand, Element::Air, Element::Air),
(Element::Air, Element::Air, Element::Sand, Element::Sand),
),
gen_rule(
(Element::Sand, Element::Sand, Element::Air, Element::Sand),
(Element::Air, Element::Sand, Element::Sand, Element::Sand),
),
gen_rule(
(Element::Sand, Element::Sand, Element::Sand, Element::Air),
(Element::Sand, Element::Air, Element::Sand, Element::Sand),
),
]),
}
}
}
impl FallingSandRules {
pub fn get_result(&self, input_rule: u32) -> u32 {
match self.rules.get(&input_rule) {
Some(&result) => result,
None => input_rule,
}
}
}