summaryrefslogtreecommitdiff
path: root/src/cell.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/cell.rs')
-rw-r--r--src/cell.rs229
1 files changed, 137 insertions, 92 deletions
diff --git a/src/cell.rs b/src/cell.rs
index b085c5e..e4be4ac 100644
--- a/src/cell.rs
+++ b/src/cell.rs
@@ -1,143 +1,188 @@
use crate::constants;
-use ggez::graphics::{
- self, spritebatch::SpriteBatch, Color, DrawMode, DrawParam, Mesh, Rect, StrokeOptions,
-};
-use ggez::mint::{Point2, Vector2};
-use ggez::{Context, GameResult};
+use bevy::prelude::*;
use rand::{
distributions::{Distribution, Standard},
Rng,
};
-use std::time::Instant;
-#[derive(Clone, Copy, PartialEq)]
+#[derive(Debug, PartialEq, Clone, Copy)]
pub enum Occupant {
None,
Green,
Yellow,
- Diamond,
Red,
- Explosion { frame: usize, timer: Instant },
+ Blue,
+ Purple,
+ Explosion,
+}
+
+impl Default for Occupant {
+ fn default() -> Occupant {
+ Occupant::None
+ }
+}
+
+impl Occupant {
+ pub fn to_index(&self) -> u32 {
+ match self {
+ Occupant::Green => constants::TILESHEET_GREEN,
+ Occupant::Yellow => constants::TILESHEET_YELLOW,
+ Occupant::Red => constants::TILESHEET_RED,
+ Occupant::Blue => constants::TILESHEET_BLUE,
+ Occupant::Purple => constants::TILESHEET_PURPLE,
+ Occupant::Explosion => constants::TILESHEET_EXPLOSION1,
+ Occupant::None => 0,
+ }
+ }
}
impl Distribution<Occupant> for Standard {
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Occupant {
- match rng.gen_range(0..=3) {
+ match rng.gen_range(0..=4) {
0 => Occupant::Green,
1 => Occupant::Yellow,
- 2 => Occupant::Diamond,
+ 2 => Occupant::Blue,
3 => Occupant::Red,
+ 4 => Occupant::Purple,
_ => Occupant::None,
}
}
}
-#[derive(Clone, Copy)]
+#[derive(Debug, Clone, Default, Copy)]
pub struct Cell {
+ pub x: usize,
+ pub y: usize,
pub occupant: Occupant,
- position: Point2<f32>,
- hover: bool,
- clicked: bool,
+ pub selected: bool,
+ pub hovered: bool,
}
impl Cell {
- pub fn new(position: Point2<f32>) -> Cell {
+ pub fn new(x: usize, y: usize) -> Cell {
Cell {
- occupant: rand::random(),
- position,
- hover: false,
- clicked: false,
+ x,
+ y,
+ occupant: Occupant::None,
+ selected: false,
+ hovered: false,
+ }
+ }
+
+ pub fn set_occupant(
+ &mut self,
+ occupant: Occupant,
+ sprite: &mut TextureAtlasSprite,
+ visible: &mut Visible,
+ ) {
+ self.occupant = occupant;
+ sprite.index = self.occupant.to_index();
+ if self.occupant == Occupant::None {
+ visible.is_visible = false;
+ } else {
+ visible.is_visible = true;
}
}
+}
- pub fn contains(&self, position: Point2<f32>) -> bool {
- position.x > self.position.x
- && position.y > self.position.y
- && position.x < self.position.x + constants::TILE_WIDTH * constants::TILE_SCALE
- && position.y < self.position.y + constants::TILE_WIDTH * constants::TILE_SCALE
+pub fn insert(mut q: Query<(&mut Cell, &mut TextureAtlasSprite, &mut Visible)>) {
+ for (mut cell, mut sprite, mut visible) in q.iter_mut() {
+ if cell.occupant == Occupant::None && cell.y == constants::GRID_SIZE - 1 {
+ cell.set_occupant(rand::random(), &mut sprite, &mut visible);
+ }
}
+}
- pub fn moveable(&self) -> bool {
- //!matches!(self.occupant, Occupant::Explosion{ ..} | Occupant::None)
- match self.occupant {
- Occupant::Explosion { .. } => false,
- Occupant::None => false,
- _ => true,
+pub fn start_explosion(mut commands: Commands, mut q: Query<(Entity, &Cell), Without<Timer>>) {
+ for (entity, cell) in q.iter_mut() {
+ if cell.occupant == Occupant::Explosion {
+ commands
+ .entity(entity)
+ .insert(Timer::from_seconds(0.1, true));
}
}
+}
- pub fn clicked_on(&mut self) {
- self.clicked = true;
+pub fn check(mut q: Query<(&mut Cell, &mut TextureAtlasSprite, &mut Visible)>) {
+ let mut cells = [[Cell::default(); constants::GRID_SIZE]; constants::GRID_SIZE];
+ for (cell, _, _) in q.iter_mut() {
+ cells[cell.x][cell.y] = *cell;
}
- pub fn clicked_off(&mut self) {
- self.clicked = false;
+ let mut last = Occupant::None;
+ let mut connected = Vec::new();
+
+ for (i, row) in cells.iter().enumerate() {
+ let mut c = Vec::new();
+ for (j, _) in row.iter().enumerate() {
+ if cells[i][j].occupant == last && last != Occupant::None && last != Occupant::Explosion
+ {
+ 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;
}
- pub fn hover_on(&mut self) {
- self.hover = true;
+ 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 && last != Occupant::Explosion
+ {
+ 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;
}
- pub fn hover_off(&mut self) {
- self.hover = false;
+ connected = connected.into_iter().filter(|c| c.len() > 4).collect();
+
+ for c in connected.iter() {
+ for (i, j) in c.iter() {
+ for (mut cell, mut sprite, mut visible) in q.iter_mut() {
+ if &cell.x == i && &cell.y == j && cell.occupant != Occupant::Explosion {
+ cell.set_occupant(Occupant::Explosion, &mut sprite, &mut visible);
+ }
+ }
+ }
}
+}
- pub fn draw(&self, context: &mut Context, spritebatch: &mut SpriteBatch) -> GameResult {
- let source = match self.occupant {
- Occupant::None => None,
- Occupant::Explosion { frame, .. } => match frame {
- 0 => Some(Rect::new(0.0, 0.5, 0.25, 0.5)),
- 1 => Some(Rect::new(0.25, 0.5, 0.25, 0.5)),
- 2 => Some(Rect::new(0.50, 0.5, 0.25, 0.5)),
- 3 => Some(Rect::new(0.75, 0.5, 0.25, 0.5)),
- _ => None,
- },
- Occupant::Green => Some(Rect::new(0.0, 0.0, 0.25, 0.5)),
- Occupant::Yellow => Some(Rect::new(0.25, 0.0, 0.25, 0.5)),
- Occupant::Diamond => Some(Rect::new(0.50, 0.0, 0.25, 0.5)),
- Occupant::Red => Some(Rect::new(0.75, 0.0, 0.25, 0.5)),
- };
-
- if let Some(source) = source {
- spritebatch.add(
- DrawParam::default()
- .src(source)
- .dest(self.position)
- .scale(Vector2 {
- x: constants::TILE_SCALE,
- y: constants::TILE_SCALE,
- }),
- );
+pub fn falling(mut q: Query<(&mut Cell, &mut TextureAtlasSprite, &mut Visible)>) {
+ let mut have_gems = Vec::new();
+ for (cell, _sprite, _visible) in q.iter_mut() {
+ if cell.occupant != Occupant::None {
+ have_gems.push(*cell);
}
+ }
- if self.hover {
- let mesh = Mesh::new_rectangle(
- context,
- DrawMode::Stroke(StrokeOptions::default()),
- Rect::new(
- self.position.x,
- self.position.y,
- constants::TILE_WIDTH * constants::TILE_SCALE,
- constants::TILE_HEIGHT * constants::TILE_SCALE,
- ),
- Color::from_rgb(255, 100, 100),
- )?;
- graphics::draw(context, &mesh, DrawParam::default())?;
+ let mut moved_gems = Vec::new();
+ for (mut cell, mut sprite, mut visible) in q.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.set_occupant(c.occupant, &mut sprite, &mut visible);
+ moved_gems.push(c);
+ }
}
- if self.clicked {
- let mesh = Mesh::new_rectangle(
- context,
- DrawMode::Stroke(StrokeOptions::default()),
- Rect::new(
- self.position.x,
- self.position.y,
- constants::TILE_WIDTH * constants::TILE_SCALE,
- constants::TILE_HEIGHT * constants::TILE_SCALE,
- ),
- Color::from_rgb(100, 255, 100),
- )?;
- graphics::draw(context, &mesh, DrawParam::default())?;
+ }
+
+ for (mut cell, mut sprite, mut visible) in q.iter_mut() {
+ if moved_gems.iter().any(|c| (c.x, c.y) == (cell.x, cell.y)) {
+ cell.set_occupant(Occupant::None, &mut sprite, &mut visible);
}
- Ok(())
}
}