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 rand::{ distributions::{Distribution, Standard}, Rng, }; use std::time::Instant; #[derive(Clone, Copy, PartialEq)] pub enum Occupant { None, Green, Yellow, Diamond, Red, Explosion { frame: usize, timer: Instant }, } impl Distribution for Standard { fn sample(&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(Clone, Copy)] pub struct Cell { pub occupant: Occupant, position: Point2, hover: bool, clicked: bool, } impl Cell { pub fn new(position: Point2) -> Cell { Cell { occupant: rand::random(), position, hover: false, clicked: false, } } pub fn contains(&self, position: Point2) -> 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 moveable(&self) -> bool { //!matches!(self.occupant, Occupant::Explosion{ ..} | Occupant::None) match self.occupant { Occupant::Explosion { .. } => false, Occupant::None => false, _ => true, } } pub fn clicked_on(&mut self) { self.clicked = true; } pub fn clicked_off(&mut self) { self.clicked = false; } pub fn hover_on(&mut self) { self.hover = true; } pub fn hover_off(&mut self) { self.hover = false; } 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, }), ); } 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())?; } 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())?; } Ok(()) } }