summaryrefslogtreecommitdiff
path: root/src/cell.rs
diff options
context:
space:
mode:
authorTom Barrett <tom@tombarrett.xyz>2021-03-21 17:51:55 +0100
committerTom Barrett <tom@tombarrett.xyz>2021-03-21 17:51:55 +0100
commit965ccb56c4c58066939d74bea22c2a9b59416d0d (patch)
tree593e332df8b2f424303c7e061159fbf3da464706 /src/cell.rs
parent911032cb80a6aeff5549e1038e19d0e0524abd3c (diff)
moved cell stuff to another file
Diffstat (limited to 'src/cell.rs')
-rw-r--r--src/cell.rs207
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();
+ }
+ }
+}