summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/cell.rs143
-rw-r--r--src/constants.rs8
-rw-r--r--src/cosmonaut.rs110
-rw-r--r--src/lib.rs3
-rw-r--r--src/main.rs284
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();
}