2022-11-25 17:20:01 +00:00
|
|
|
//! Gameboard view.
|
|
|
|
|
2022-11-25 20:37:57 +00:00
|
|
|
use graphics::character::CharacterCache;
|
2022-11-25 17:20:01 +00:00
|
|
|
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,
|
2022-11-25 20:37:57 +00:00
|
|
|
pub text_color: Color,
|
2022-11-26 14:42:41 +00:00
|
|
|
pub loaded_cell_background_color: Color,
|
2022-11-26 21:09:32 +00:00
|
|
|
pub invalid_cell_background_color: Color,
|
|
|
|
pub invalid_selected_cell_background_color: Color,
|
|
|
|
pub completed_background_color: Color,
|
2022-11-25 17:20:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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],
|
2022-11-25 20:37:57 +00:00
|
|
|
text_color: [0.0, 0.0, 0.1, 1.0],
|
2022-11-26 14:42:41 +00:00
|
|
|
loaded_cell_background_color: [1.0, 1.0, 1.0, 1.0],
|
2022-11-26 21:09:32 +00:00
|
|
|
invalid_cell_background_color: [1.0, 0.0, 0.0, 1.0],
|
|
|
|
invalid_selected_cell_background_color: [1.0, 0.0, 0.5, 1.0],
|
|
|
|
completed_background_color: [0.0, 1.0, 0.0, 1.0],
|
2022-11-25 17:20:01 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub struct GameboardView {
|
|
|
|
pub settings: GameboardViewSettings,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl GameboardView {
|
|
|
|
pub fn new(settings: GameboardViewSettings) -> GameboardView {
|
|
|
|
GameboardView { settings: settings }
|
|
|
|
}
|
|
|
|
|
2022-11-25 20:37:57 +00:00
|
|
|
pub fn draw<G: Graphics, C>(
|
|
|
|
&self,
|
|
|
|
controller: &GameboardController,
|
|
|
|
glyphs: &mut C,
|
|
|
|
c: &Context,
|
|
|
|
g: &mut G,
|
|
|
|
) where
|
|
|
|
C: CharacterCache<Texture = G::Texture>,
|
|
|
|
{
|
|
|
|
use graphics::{Image, Line, Rectangle, Transformed};
|
2022-11-25 17:20:01 +00:00
|
|
|
|
|
|
|
let ref settings = self.settings;
|
|
|
|
let board_rect = [
|
|
|
|
settings.position[0],
|
|
|
|
settings.position[1],
|
|
|
|
settings.size,
|
|
|
|
settings.size,
|
|
|
|
];
|
|
|
|
|
2022-11-26 21:09:32 +00:00
|
|
|
if controller.gameboard.completed {
|
|
|
|
Rectangle::new(settings.completed_background_color).draw(
|
|
|
|
board_rect,
|
|
|
|
&c.draw_state,
|
|
|
|
c.transform,
|
|
|
|
g,
|
|
|
|
);
|
|
|
|
} else {
|
|
|
|
Rectangle::new(settings.background_color).draw(
|
|
|
|
board_rect,
|
|
|
|
&c.draw_state,
|
|
|
|
c.transform,
|
|
|
|
g,
|
|
|
|
);
|
2022-11-25 17:20:01 +00:00
|
|
|
|
2022-11-26 21:09:32 +00:00
|
|
|
for i in 0..9 {
|
|
|
|
for j in 0..9 {
|
|
|
|
if controller.gameboard.cells[i][j].loaded {
|
|
|
|
color_cell(
|
|
|
|
settings,
|
|
|
|
[j, i],
|
|
|
|
settings.loaded_cell_background_color,
|
|
|
|
c,
|
|
|
|
g,
|
|
|
|
);
|
|
|
|
} else if controller.gameboard.cells[i][j].invalid {
|
|
|
|
color_cell(
|
|
|
|
settings,
|
|
|
|
[j, i],
|
|
|
|
settings.invalid_cell_background_color,
|
|
|
|
c,
|
|
|
|
g,
|
|
|
|
);
|
|
|
|
}
|
2022-11-26 14:42:41 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-11-26 21:09:32 +00:00
|
|
|
if let Some(ind) = controller.selected_cell {
|
|
|
|
let cell = controller.gameboard.cells[ind[1]][ind[0]];
|
|
|
|
let color = if !cell.loaded {
|
|
|
|
if !cell.invalid {
|
|
|
|
settings.selected_cell_background_color
|
|
|
|
} else {
|
|
|
|
settings.invalid_selected_cell_background_color
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
settings.loaded_cell_background_color
|
|
|
|
};
|
|
|
|
color_cell(settings, ind, color, c, g);
|
|
|
|
}
|
2022-11-25 17:20:01 +00:00
|
|
|
}
|
|
|
|
|
2022-11-25 20:37:57 +00:00
|
|
|
let text_image = Image::new_color(settings.text_color);
|
|
|
|
let cell_size = settings.size / 9.0;
|
|
|
|
|
|
|
|
for j in 0..9 {
|
|
|
|
for i in 0..9 {
|
|
|
|
if let Some(ch) = controller.gameboard.char([i, j]) {
|
|
|
|
let pos = [
|
|
|
|
settings.position[0] + i as f64 * cell_size + 15.0,
|
|
|
|
settings.position[1] + j as f64 * cell_size + 34.0,
|
|
|
|
];
|
|
|
|
|
|
|
|
if let Ok(character) = glyphs.character(34, ch) {
|
|
|
|
let ch_x = pos[0] + character.left();
|
|
|
|
let ch_y = pos[1] - character.top();
|
|
|
|
let text_image = text_image.src_rect([
|
|
|
|
character.atlas_offset[0],
|
|
|
|
character.atlas_offset[1],
|
|
|
|
character.atlas_size[0],
|
|
|
|
character.atlas_size[1],
|
|
|
|
]);
|
|
|
|
text_image.draw(
|
|
|
|
character.texture,
|
|
|
|
&c.draw_state,
|
|
|
|
c.transform.trans(ch_x, ch_y),
|
|
|
|
g,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-11-25 17:20:01 +00:00
|
|
|
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,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
2022-11-26 14:42:41 +00:00
|
|
|
|
|
|
|
fn color_cell<G: Graphics>(
|
|
|
|
settings: &GameboardViewSettings,
|
|
|
|
ind: [usize; 2],
|
|
|
|
color: [f32; 4],
|
|
|
|
c: &Context,
|
|
|
|
g: &mut G,
|
|
|
|
) {
|
|
|
|
use graphics::Rectangle;
|
|
|
|
|
|
|
|
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(color).draw(cell_rect, &c.draw_state, c.transform, g);
|
|
|
|
}
|