diff options
Diffstat (limited to 'src/cell.rs')
-rw-r--r-- | src/cell.rs | 207 |
1 files changed, 207 insertions, 0 deletions
diff --git a/src/cell.rs b/src/cell.rs new file mode 100644 index 0000000..6b42fdf --- /dev/null +++ b/src/cell.rs @@ -0,0 +1,207 @@ +use crate::constants; +use bevy::prelude::*; +use rand::{ + distributions::{Distribution, Standard}, + Rng, +}; + +#[derive(Debug, PartialEq, Clone, Copy)] +pub enum Occupant { + None, + Green, + Yellow, + Red, + Diamond, + Explosion, +} + +impl Default for Occupant { + fn default() -> Occupant { + Occupant::None + } +} + +impl Occupant { + pub fn to_index(&self) -> u32 { + match self { + Occupant::Green => 0, + Occupant::Yellow => 1, + Occupant::Red => 2, + Occupant::Diamond => 3, + Occupant::Explosion => 4, + Occupant::None => 13, + } + } +} + +impl Distribution<Occupant> for Standard { + fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Occupant { + match rng.gen_range(0..=3) { + 0 => Occupant::Green, + 1 => Occupant::Yellow, + 2 => Occupant::Diamond, + 3 => Occupant::Red, + _ => Occupant::None, + } + } +} + +#[derive(Debug, Clone, Default, Copy)] +pub struct Cell { + pub x: usize, + pub y: usize, + pub occupant: Occupant, + pub selected: bool, + pub hovered: bool, +} + +impl Cell { + pub fn new(x: usize, y: usize) -> Cell { + Cell { + x, + y, + occupant: Occupant::None, + selected: false, + hovered: false, + } + } +} + +pub fn insert(mut cell_query: Query<(&mut Cell, &mut TextureAtlasSprite)>) { + for (mut cell, mut sprite) in cell_query.iter_mut() { + if cell.occupant == Occupant::None && cell.y == constants::ROWS - 1 { + cell.occupant = rand::random(); + sprite.index = cell.occupant.to_index(); + } + } +} + +pub fn explosion_animation( + time: Res<Time>, + commands: &mut Commands, + mut cell_query: Query<( + Entity, + &mut Cell, + &mut TextureAtlasSprite, + Option<&mut Timer>, + )>, +) { + for (entity, mut cell, mut sprite, timer) in cell_query.iter_mut() { + if cell.occupant == Occupant::Explosion { + if let Some(mut timer) = timer { + timer.tick(time.delta_seconds()); + if timer.finished() { + if sprite.index < 7 && sprite.index >= 4 { + sprite.index += 1; + } else { + cell.occupant = Occupant::None; + sprite.index = cell.occupant.to_index(); + commands.remove_one::<Timer>(entity); + } + } + } else { + commands.insert(entity, (Timer::from_seconds(0.1, true),)); + } + } + } +} + +pub fn check(mut cell_query: Query<(&mut Cell, &mut TextureAtlasSprite)>) { + let mut cells = [[Cell::default(); constants::COLUMNS]; constants::ROWS]; + for (cell, _) in cell_query.iter_mut() { + cells[cell.x][cell.y] = *cell; + } + + let mut last = Occupant::None; + let mut connected = Vec::new(); + + for (i, _) in cells.iter().enumerate() { + let mut c = Vec::new(); + for j in 0..constants::ROWS { + if cells[i][j].occupant == last && last != Occupant::None { + c.push((i, j)); + c.push((i, j - 1)); + } else { + connected.push(c.clone()); + c.clear(); + } + last = cells[i][j].occupant; + } + connected.push(c); + last = Occupant::None; + } + + for c in connected.iter() { + if c.len() > 4 { + for (i, j) in c.iter() { + for (mut cell, mut sprite) in cell_query.iter_mut() { + if &cell.x == i && &cell.y == j && cell.occupant != Occupant::Explosion { + cell.occupant = Occupant::Explosion; + sprite.index = cell.occupant.to_index(); + } + } + } + } + } + + connected.clear(); + + for (i, row) in cells.iter().enumerate() { + let mut c = Vec::new(); + for (j, _) in row.iter().enumerate() { + if cells[j][i].occupant == last && last != Occupant::None { + c.push((j, i)); + c.push((j - 1, i)); + } else { + connected.push(c.clone()); + c.clear(); + } + last = cells[j][i].occupant; + } + connected.push(c); + last = Occupant::None; + } + + for c in connected.iter() { + if c.len() > 4 { + for (i, j) in c.iter() { + for (mut cell, mut sprite) in cell_query.iter_mut() { + if &cell.x == i && &cell.y == j && cell.occupant != Occupant::Explosion { + cell.occupant = Occupant::Explosion; + sprite.index = cell.occupant.to_index(); + } + } + } + } + } +} + +pub fn falling(mut cell_query: Query<(&mut Cell, &mut TextureAtlasSprite)>) { + let mut have_gems = Vec::new(); + for (cell, _sprite) in cell_query.iter_mut() { + if cell.occupant != Occupant::None { + have_gems.push(*cell); + } + } + + let mut moved_gems = Vec::new(); + for (mut cell, mut sprite) in cell_query.iter_mut() { + if cell.occupant == Occupant::None { + if let Some(c) = have_gems + .iter() + .find(|&c| (c.x, c.y) == (cell.x, cell.y + 1)) + { + cell.occupant = c.occupant; + sprite.index = cell.occupant.to_index(); + moved_gems.push(c); + } + } + } + + for (mut cell, mut sprite) in cell_query.iter_mut() { + if moved_gems.iter().any(|c| (c.x, c.y) == (cell.x, cell.y)) { + cell.occupant = Occupant::None; + sprite.index = cell.occupant.to_index(); + } + } +} |