diff --git a/piston-tutorials/sudoku/src/gameboard.rs b/piston-tutorials/sudoku/src/gameboard.rs new file mode 100644 index 0000000..e902dc8 --- /dev/null +++ b/piston-tutorials/sudoku/src/gameboard.rs @@ -0,0 +1,15 @@ +//! Game board logic. + +const SIZE: usize = 9; + +pub struct Gameboard { + pub cells: [[u8; SIZE]; SIZE], +} + +impl Gameboard { + pub fn new() -> Gameboard { + Gameboard { + cells: [[0; SIZE]; SIZE], + } + } +} diff --git a/piston-tutorials/sudoku/src/gameboard_controller.rs b/piston-tutorials/sudoku/src/gameboard_controller.rs new file mode 100644 index 0000000..f0a3a64 --- /dev/null +++ b/piston-tutorials/sudoku/src/gameboard_controller.rs @@ -0,0 +1,40 @@ +//! Gameboard controller + +use piston::GenericEvent; + +use crate::Gameboard; + +pub struct GameboardController { + pub gameboard: Gameboard, + pub selected_cell: Option<[usize; 2]>, + cursor_pos: [f64; 2], +} + +impl GameboardController { + pub fn new(gameboard: Gameboard) -> GameboardController { + GameboardController { + gameboard: gameboard, + selected_cell: None, + cursor_pos: [0.0; 2], + } + } + + pub fn event(&mut self, pos: [f64; 2], size: f64, e: &E) { + use piston::input::{Button, MouseButton}; + + if let Some(pos) = e.mouse_cursor_args() { + self.cursor_pos = pos; + } + + if let Some(Button::Mouse(MouseButton::Left)) = e.press_args() { + let x = self.cursor_pos[0] - pos[0]; + let y = self.cursor_pos[1] - pos[1]; + + if x >= 0.0 && x < size && y >= 0.0 && y < size { + let cell_x = (x / size * 9.0) as usize; + let cell_y = (y / size * 9.0) as usize; + self.selected_cell = Some([cell_x, cell_y]); + } + } + } +} diff --git a/piston-tutorials/sudoku/src/gameboard_view.rs b/piston-tutorials/sudoku/src/gameboard_view.rs new file mode 100644 index 0000000..f7a23f4 --- /dev/null +++ b/piston-tutorials/sudoku/src/gameboard_view.rs @@ -0,0 +1,107 @@ +//! Gameboard view. + +use graphics::types::Color; +use graphics::{Context, Graphics}; + +use crate::gameboard_controller::GameboardController; + +pub struct GameboardViewSettings { + pub position: [f64; 2], + pub size: f64, + pub background_color: Color, + pub border_color: Color, + pub board_edge_color: Color, + pub section_edge_color: Color, + pub cell_edge_color: Color, + pub board_edge_radius: f64, + pub section_edge_radius: f64, + pub cell_edge_radius: f64, + pub selected_cell_background_color: Color, +} + +impl GameboardViewSettings { + pub fn new() -> GameboardViewSettings { + GameboardViewSettings { + position: [10.0; 2], + size: 400.0, + background_color: [0.8, 0.8, 1.0, 1.0], + border_color: [0.0, 0.0, 0.2, 1.0], + board_edge_color: [0.0, 0.0, 0.2, 1.0], + section_edge_color: [0.0, 0.0, 0.2, 1.0], + cell_edge_color: [0.0, 0.0, 0.2, 1.0], + board_edge_radius: 3.0, + section_edge_radius: 2.0, + cell_edge_radius: 1.0, + selected_cell_background_color: [0.9, 0.9, 1.0, 1.0], + } + } +} + +pub struct GameboardView { + pub settings: GameboardViewSettings, +} + +impl GameboardView { + pub fn new(settings: GameboardViewSettings) -> GameboardView { + GameboardView { settings: settings } + } + + pub fn draw(&self, controller: &GameboardController, c: &Context, g: &mut G) { + use graphics::{Line, Rectangle}; + + let ref settings = self.settings; + let board_rect = [ + settings.position[0], + settings.position[1], + settings.size, + settings.size, + ]; + + Rectangle::new(settings.background_color).draw(board_rect, &c.draw_state, c.transform, g); + + if let Some(ind) = controller.selected_cell { + let cell_size = settings.size / 9.0; + let pos = [ind[0] as f64 * cell_size, ind[1] as f64 * cell_size]; + let cell_rect = [ + settings.position[0] + pos[0], + settings.position[1] + pos[1], + cell_size, + cell_size, + ]; + Rectangle::new(settings.selected_cell_background_color).draw( + cell_rect, + &c.draw_state, + c.transform, + g, + ); + } + + let cell_edge = Line::new(settings.cell_edge_color, settings.cell_edge_radius); + let section_edge = Line::new(settings.section_edge_color, settings.section_edge_radius); + + for i in 0..9 { + let x = settings.position[0] + i as f64 / 9.0 * settings.size; + let y = settings.position[1] + i as f64 / 9.0 * settings.size; + let x2 = settings.position[0] + settings.size; + let y2 = settings.position[1] + settings.size; + + let vline = [x, settings.position[1], x, y2]; + let hline = [settings.position[0], y, x2, y]; + + if (i % 3) == 0 { + section_edge.draw(vline, &c.draw_state, c.transform, g); + section_edge.draw(hline, &c.draw_state, c.transform, g); + } else { + cell_edge.draw(vline, &c.draw_state, c.transform, g); + cell_edge.draw(hline, &c.draw_state, c.transform, g); + } + } + + Rectangle::new_border(settings.board_edge_color, settings.board_edge_radius).draw( + board_rect, + &c.draw_state, + c.transform, + g, + ); + } +} diff --git a/piston-tutorials/sudoku/src/main.rs b/piston-tutorials/sudoku/src/main.rs index 768c0bd..53c5aa0 100644 --- a/piston-tutorials/sudoku/src/main.rs +++ b/piston-tutorials/sudoku/src/main.rs @@ -1,4 +1,4 @@ -#![deny(missing_docs)] +//////#![deny(missing_docs)] //! An Sudoko please. @@ -9,6 +9,14 @@ use opengl_graphics::{GlGraphics, OpenGL}; use piston::event_loop::{EventSettings, Events}; use piston::{EventLoop, RenderEvent, WindowSettings}; +pub use crate::gameboard::Gameboard; +pub use crate::gameboard_controller::GameboardController; +pub use crate::gameboard_view::{GameboardView, GameboardViewSettings}; + +mod gameboard; +mod gameboard_controller; +mod gameboard_view; + fn main() { let opengl = OpenGL::V3_2; let settings = WindowSettings::new("Sudoku", (640, 480)) @@ -19,12 +27,23 @@ fn main() { let mut events = Events::new(EventSettings::new().lazy(true)); let mut gl = GlGraphics::new(opengl); + let gameboard = Gameboard::new(); + let mut gameboard_controller = GameboardController::new(gameboard); + let gameboard_view_settings = GameboardViewSettings::new(); + let gameboard_view = GameboardView::new(gameboard_view_settings); + while let Some(e) = events.next(&mut window) { + gameboard_controller.event( + gameboard_view.settings.position, + gameboard_view.settings.size, + &e, + ); if let Some(args) = e.render_args() { gl.draw(args.viewport(), |c, g| { use graphics::clear; clear([1.0; 4], g); + gameboard_view.draw(&gameboard_controller, &c, g); }) } }