diff options
author | Tom Barrett <tom@tombarrett.xyz> | 2021-03-14 21:03:53 +0100 |
---|---|---|
committer | Tom Barrett <tom@tombarrett.xyz> | 2021-03-14 21:03:53 +0100 |
commit | a0c406ca212ed4f2a3bc41bbdacc789ee57da42e (patch) | |
tree | 52c8ba4152b459c96b867ced8b37103b9b06a9fe /src | |
parent | e3238817205b2c5d2504330135ffc552881b1a73 (diff) |
split up into multiple files
Diffstat (limited to 'src')
-rw-r--r-- | src/cell.rs | 143 | ||||
-rw-r--r-- | src/constants.rs | 8 | ||||
-rw-r--r-- | src/cosmonaut.rs | 110 | ||||
-rw-r--r-- | src/lib.rs | 3 | ||||
-rw-r--r-- | src/main.rs | 284 |
5 files changed, 283 insertions, 265 deletions
diff --git a/src/cell.rs b/src/cell.rs new file mode 100644 index 0000000..b085c5e --- /dev/null +++ b/src/cell.rs @@ -0,0 +1,143 @@ +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<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(Clone, Copy)] +pub struct Cell { + pub occupant: Occupant, + position: Point2<f32>, + hover: bool, + clicked: bool, +} + +impl Cell { + pub fn new(position: Point2<f32>) -> Cell { + Cell { + occupant: rand::random(), + position, + hover: false, + clicked: false, + } + } + + 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 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(()) + } +} diff --git a/src/constants.rs b/src/constants.rs new file mode 100644 index 0000000..f9a5003 --- /dev/null +++ b/src/constants.rs @@ -0,0 +1,8 @@ +pub const TILE_SCALE: f32 = 3.0; +pub const TILE_HEIGHT: f32 = 16.0; +pub const TILE_WIDTH: f32 = 16.0; +pub const BORDER_SIZE: f32 = 3.0; +pub const SHIFT_X: f32 = 50.0; +pub const SHIFT_Y: f32 = 50.0; +pub const COLUMNS: usize = 8; +pub const ROWS: usize = 8; diff --git a/src/cosmonaut.rs b/src/cosmonaut.rs new file mode 100644 index 0000000..235861e --- /dev/null +++ b/src/cosmonaut.rs @@ -0,0 +1,110 @@ +use crate::constants; +use ggez::graphics::{self, DrawParam, FilterMode, Image, Rect}; +use ggez::mint::{Point2, Vector2}; +use ggez::{Context, GameResult}; +use std::time::Instant; + +#[derive(Clone, Copy)] +enum CosmonautFrames { + None, + One, + Two, + Three, + Four, +} + +impl CosmonautFrames { + pub fn next(&mut self) { + *self = match self { + CosmonautFrames::None => CosmonautFrames::One, + CosmonautFrames::One => CosmonautFrames::Two, + CosmonautFrames::Two => CosmonautFrames::Three, + CosmonautFrames::Three => CosmonautFrames::Four, + CosmonautFrames::Four => CosmonautFrames::None, + }; + } +} + +pub struct Cosmonaut { + destination: Point2<f32>, + image: Image, + frame: CosmonautFrames, + timer: Instant, + scale: Vector2<f32>, +} + +impl Cosmonaut { + pub fn new(context: &mut Context) -> GameResult<Cosmonaut> { + let mut image = Image::new(context, "/cosmonaut.png")?; + image.set_filter(FilterMode::Nearest); + + Ok(Cosmonaut { + image, + destination: Point2 { x: 600.0, y: 200.0 }, + frame: CosmonautFrames::None, + timer: Instant::now(), + scale: Vector2 { + x: constants::TILE_SCALE * 2.0, + y: constants::TILE_SCALE * 2.0, + }, + }) + } + + pub fn draw(&self, context: &mut Context) -> GameResult { + graphics::draw( + context, + &self.image, + DrawParam::default() + .dest(self.destination) + .scale(self.scale) + .src(Rect::new(0.0, 0.0, 1.0 / 3.0, 1.0)), + )?; + let source = match self.frame { + CosmonautFrames::None => None, + CosmonautFrames::One => Some(Rect::new(1.0 / 3.0, 0.0, 1.0 / 3.0, 1.0 / 2.0)), + CosmonautFrames::Two => Some(Rect::new(2.0 / 3.0, 0.0, 1.0, 1.0 / 2.0)), + CosmonautFrames::Three => Some(Rect::new(1.0 / 3.0, 1.0 / 2.0, 1.0 / 3.0, 1.0 / 2.0)), + CosmonautFrames::Four => Some(Rect::new(2.0 / 3.0, 1.0 / 2.0, 1.0, 1.0)), + }; + if let Some(source) = source { + graphics::draw( + context, + &self.image, + DrawParam::default() + .dest(self.destination) + .src(source) + .scale(self.scale), + )?; + } + + Ok(()) + } + + pub fn update(&mut self) { + match self.frame { + CosmonautFrames::None => (), + _ => { + if self.timer.elapsed().as_millis() > 50 { + self.frame.next(); + self.timer = Instant::now(); + } + } + } + } + + pub fn start(&mut self) { + if let CosmonautFrames::None = self.frame { + if self.timer.elapsed().as_secs() > 5 { + self.timer = Instant::now(); + self.frame.next() + } + } + } + + pub fn contains(&self, position: Point2<f32>) -> bool { + position.x > self.destination.x + && position.y > self.destination.y + && position.x < self.destination.x + constants::TILE_WIDTH * constants::TILE_SCALE * 2.0 + && position.y < self.destination.y + constants::TILE_WIDTH * constants::TILE_SCALE * 2.0 + } +} diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..9b47535 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,3 @@ +pub mod cell; +pub mod constants; +pub mod cosmonaut; diff --git a/src/main.rs b/src/main.rs index 13c5c6c..bff0079 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,261 +1,13 @@ use ggez::event::{self, EventHandler}; -use ggez::graphics::{ - self, spritebatch::SpriteBatch, Color, DrawMode, DrawParam, FilterMode, Image, Mesh, Rect, - StrokeOptions, WrapMode, -}; +use ggez::graphics::{self, spritebatch::SpriteBatch, DrawParam, FilterMode, Image, WrapMode}; use ggez::input::mouse; -use ggez::mint::{Point2, Vector2}; +use ggez::mint::Point2; use ggez::{Context, ContextBuilder, GameResult}; -use rand::{ - distributions::{Distribution, Standard}, - Rng, -}; use std::time::Instant; -pub const TILE_SCALE: f32 = 3.0; -pub const TILE_HEIGHT: f32 = 16.0; -pub const TILE_WIDTH: f32 = 16.0; -pub const BORDER_SIZE: f32 = 3.0; -pub const SHIFT_X: f32 = 50.0; -pub const SHIFT_Y: f32 = 50.0; -pub const COLUMNS: usize = 8; -pub const ROWS: usize = 8; - -#[derive(Clone, Copy, PartialEq)] -enum Occupant { - None, - Green, - Yellow, - Diamond, - Red, - Explosion { frame: usize, timer: Instant }, -} - -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(Clone, Copy)] -enum CosmonautFrames { - None, - One, - Two, - Three, - Four, -} - -impl CosmonautFrames { - pub fn next(&mut self) { - *self = match self { - CosmonautFrames::None => CosmonautFrames::One, - CosmonautFrames::One => CosmonautFrames::Two, - CosmonautFrames::Two => CosmonautFrames::Three, - CosmonautFrames::Three => CosmonautFrames::Four, - CosmonautFrames::Four => CosmonautFrames::None, - }; - } -} - -struct Cosmonaut { - destination: Point2<f32>, - image: Image, - frame: CosmonautFrames, - timer: Instant, - scale: Vector2<f32>, -} - -impl Cosmonaut { - pub fn new(context: &mut Context) -> GameResult<Cosmonaut> { - let mut image = Image::new(context, "/cosmonaut.png")?; - image.set_filter(FilterMode::Nearest); - - Ok(Cosmonaut { - image, - destination: Point2 { x: 600.0, y: 200.0 }, - frame: CosmonautFrames::None, - timer: Instant::now(), - scale: Vector2 { - x: TILE_SCALE * 2.0, - y: TILE_SCALE * 2.0, - }, - }) - } - - pub fn draw(&self, context: &mut Context) -> GameResult { - graphics::draw( - context, - &self.image, - DrawParam::default() - .dest(self.destination) - .scale(self.scale) - .src(Rect::new(0.0, 0.0, 1.0 / 3.0, 1.0)), - )?; - let source = match self.frame { - CosmonautFrames::None => None, - CosmonautFrames::One => Some(Rect::new(1.0 / 3.0, 0.0, 1.0 / 3.0, 1.0 / 2.0)), - CosmonautFrames::Two => Some(Rect::new(2.0 / 3.0, 0.0, 1.0, 1.0 / 2.0)), - CosmonautFrames::Three => Some(Rect::new(1.0 / 3.0, 1.0 / 2.0, 1.0 / 3.0, 1.0 / 2.0)), - CosmonautFrames::Four => Some(Rect::new(2.0 / 3.0, 1.0 / 2.0, 1.0, 1.0)), - }; - if let Some(source) = source { - graphics::draw( - context, - &self.image, - DrawParam::default() - .dest(self.destination) - .src(source) - .scale(self.scale), - )?; - } - - Ok(()) - } - - pub fn update(&mut self) { - match self.frame { - CosmonautFrames::None => (), - _ => { - if self.timer.elapsed().as_millis() > 50 { - self.frame.next(); - self.timer = Instant::now(); - } - } - } - } - - pub fn start(&mut self) { - if let CosmonautFrames::None = self.frame { - if self.timer.elapsed().as_secs() > 5 { - self.timer = Instant::now(); - self.frame.next() - } - } - } - - pub fn contains(&self, position: Point2<f32>) -> bool { - position.x > self.destination.x - && position.y > self.destination.y - && position.x < self.destination.x + TILE_WIDTH * TILE_SCALE * 2.0 - && position.y < self.destination.y + TILE_WIDTH * TILE_SCALE * 2.0 - } -} - -#[derive(Clone, Copy)] -struct Cell { - occupant: Occupant, - position: Point2<f32>, - hover: bool, - clicked: bool, -} - -impl Cell { - pub fn new(position: Point2<f32>) -> Cell { - Cell { - occupant: rand::random(), - position, - hover: false, - clicked: false, - } - } - - pub fn contains(&self, position: Point2<f32>) -> bool { - position.x > self.position.x - && position.y > self.position.y - && position.x < self.position.x + TILE_WIDTH * TILE_SCALE - && position.y < self.position.y + TILE_WIDTH * TILE_SCALE - } - - pub fn moveable(&self) -> bool { - 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: TILE_SCALE, - y: TILE_SCALE, - }), - ); - } - - if self.hover { - let mesh = Mesh::new_rectangle( - context, - DrawMode::Stroke(StrokeOptions::default()), - Rect::new( - self.position.x, - self.position.y, - TILE_WIDTH * TILE_SCALE, - TILE_HEIGHT * 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, - TILE_WIDTH * TILE_SCALE, - TILE_HEIGHT * TILE_SCALE, - ), - Color::from_rgb(100, 255, 100), - )?; - graphics::draw(context, &mesh, DrawParam::default())?; - } - Ok(()) - } -} +use gems::cell::{Cell, Occupant}; +use gems::constants; +use gems::cosmonaut::Cosmonaut; struct Game { selected: Option<(usize, usize)>, @@ -277,15 +29,17 @@ impl Game { let mut grid = Vec::new(); let mut y = 0.0; - for _ in 0..COLUMNS { + for _ in 0..constants::COLUMNS { let mut column = Vec::new(); - for j in 0..ROWS { + for j in 0..constants::ROWS { column.push(Cell::new(Point2 { - x: (j as f32) * (TILE_WIDTH * TILE_SCALE + BORDER_SIZE) + SHIFT_X, - y: y + SHIFT_Y, + x: (j as f32) + * (constants::TILE_WIDTH * constants::TILE_SCALE + constants::BORDER_SIZE) + + constants::SHIFT_X, + y: y + constants::SHIFT_Y, })); } - y += TILE_HEIGHT * TILE_SCALE + BORDER_SIZE; + y += constants::TILE_HEIGHT * constants::TILE_SCALE + constants::BORDER_SIZE; grid.push(column); } @@ -301,9 +55,9 @@ impl Game { fn update_explosions(&mut self) { let mut last = Occupant::None; let mut connected = Vec::new(); - for i in 0..COLUMNS { + for i in 0..constants::COLUMNS { let mut c = Vec::new(); - for j in 0..ROWS { + for j in 0..constants::ROWS { if self.grid[i][j].occupant == last && last != Occupant::None { c.push((i, j)); c.push((i, j - 1)); @@ -329,9 +83,9 @@ impl Game { } connected.clear(); - for i in 0..COLUMNS { + for i in 0..constants::COLUMNS { let mut c = Vec::new(); - for j in 0..ROWS { + for j in 0..constants::ROWS { if self.grid[j][i].occupant == last && last != Occupant::None { c.push((j, i)); c.push((j - 1, i)); @@ -358,8 +112,8 @@ impl Game { } fn update_dropping(&mut self) { - for i in 1..COLUMNS { - for j in 0..ROWS { + for i in 1..constants::COLUMNS { + for j in 0..constants::ROWS { if self.grid[i][j].occupant == Occupant::None && self.grid[i - 1][j].occupant != Occupant::None { @@ -371,7 +125,7 @@ impl Game { } fn update_feeding(&mut self) { - for i in 0..COLUMNS { + for i in 0..constants::COLUMNS { if self.grid[0][i].occupant == Occupant::None { self.grid[0][i].occupant = rand::random(); } |