Finish, mudinji pochi
This commit is contained in:
parent
d758d03f2d
commit
c551715a52
@ -4,6 +4,8 @@ Goal: Generate 'hard' puzzles.
|
||||
|
||||
### Play a demo of the game [here](https://games.neophyte.me/sol_chess/)
|
||||
|
||||

|
||||
|
||||
## Install
|
||||
|
||||
- Install Rust from [here](https://www.rust-lang.org/tools/install).
|
||||
|
BIN
img/sol_chess.png
Normal file
BIN
img/sol_chess.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 271 KiB |
128
src/game.rs
128
src/game.rs
@ -3,8 +3,10 @@ use std::{
|
||||
fmt::{self, Display, Formatter},
|
||||
};
|
||||
|
||||
use button::{Button, ButtonColor};
|
||||
use button::Button;
|
||||
use color::UiColor;
|
||||
use macroquad::{math, prelude::*, rand};
|
||||
use shadow::draw_shadow;
|
||||
use sol_chess::{
|
||||
board::{Board, BoardState},
|
||||
generator::{self, RandomRange},
|
||||
@ -12,6 +14,8 @@ use sol_chess::{
|
||||
use texture::PieceTexture;
|
||||
|
||||
pub mod button;
|
||||
pub mod color;
|
||||
pub mod shadow;
|
||||
pub mod texture;
|
||||
|
||||
pub struct MacroquadRandAdapter;
|
||||
@ -43,11 +47,14 @@ pub struct Game {
|
||||
square_width: f32,
|
||||
window_height: f32,
|
||||
window_width: f32,
|
||||
board_rect: Rect,
|
||||
squares: Vec<GameSquare>,
|
||||
heading_rect: Rect,
|
||||
heading_font_size: f32,
|
||||
gp_btns: HashMap<ButtonAction, Button>,
|
||||
mode_btns: HashMap<GameMode, Button>,
|
||||
rules: bool,
|
||||
rules_btn: Vec<Button>,
|
||||
}
|
||||
|
||||
struct GameSquare {
|
||||
@ -89,6 +96,7 @@ impl Game {
|
||||
Self {
|
||||
original_board: board.clone(),
|
||||
board,
|
||||
board_rect: Rect::new(0., 0., 0., 0.),
|
||||
squares: Vec::new(),
|
||||
heading_rect: Rect::new(0., 0., 0., 0.),
|
||||
heading_text: "Solitaire Chess".to_string(),
|
||||
@ -100,6 +108,8 @@ impl Game {
|
||||
debug: false,
|
||||
gp_btns: HashMap::new(),
|
||||
mode_btns: HashMap::new(),
|
||||
rules: false,
|
||||
rules_btn: Vec::new(),
|
||||
window_height: 0.,
|
||||
window_width: 0.,
|
||||
square_width: 0.,
|
||||
@ -127,29 +137,54 @@ impl Game {
|
||||
}
|
||||
|
||||
pub fn handle_input(&mut self) {
|
||||
let mut btn_clicked = None;
|
||||
let mut gp_btn_clicked = None;
|
||||
for btn in &mut self.gp_btns {
|
||||
btn.1.handle_input();
|
||||
if btn.1.is_clicked() {
|
||||
btn_clicked = Some(btn.0.clone());
|
||||
gp_btn_clicked = Some(btn.0.clone());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(action) = btn_clicked {
|
||||
if let Some(action) = gp_btn_clicked {
|
||||
match action {
|
||||
ButtonAction::Reset => self.reset(),
|
||||
ButtonAction::Next => self.next_puzzle(),
|
||||
}
|
||||
} else {
|
||||
let mut mode_btn_clicked = None;
|
||||
for btn in &mut self.mode_btns {
|
||||
btn.1.handle_input();
|
||||
if btn.1.is_clicked() {
|
||||
mode_btn_clicked = Some(btn);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(btn) = mode_btn_clicked {
|
||||
self.game_mode = *btn.0;
|
||||
self.next_puzzle();
|
||||
} else {
|
||||
let mut rules_btn_clicked = false;
|
||||
for btn in &mut self.rules_btn {
|
||||
btn.handle_input();
|
||||
if btn.is_clicked() {
|
||||
rules_btn_clicked = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if rules_btn_clicked {
|
||||
self.rules = !self.rules;
|
||||
if self.rules {
|
||||
self.rules_btn[0].text = "Close".to_string();
|
||||
self.rules_btn[0].color = UiColor::Green;
|
||||
} else {
|
||||
self.rules_btn[0].text = "Rules".to_string();
|
||||
self.rules_btn[0].color = UiColor::Brown;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for btn in &mut self.mode_btns {
|
||||
@ -160,6 +195,11 @@ impl Game {
|
||||
}
|
||||
}
|
||||
|
||||
if is_key_released(KeyCode::Escape) {
|
||||
self.rules = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if is_key_released(KeyCode::D) {
|
||||
self.debug = !self.debug;
|
||||
return;
|
||||
@ -218,15 +258,45 @@ impl Game {
|
||||
}
|
||||
|
||||
fn draw_board(&self) {
|
||||
let board_shadow_width = 0.1 * self.square_width;
|
||||
draw_shadow(self.board_rect, board_shadow_width);
|
||||
|
||||
if self.rules {
|
||||
draw_rectangle(
|
||||
self.board_rect.x,
|
||||
self.board_rect.y,
|
||||
self.board_rect.w,
|
||||
self.board_rect.h,
|
||||
UiColor::Brown.to_bg_color(),
|
||||
);
|
||||
|
||||
let font_size = self.heading_font_size * 0.8;
|
||||
let rules = "\
|
||||
Every move should be a \n\
|
||||
capture. Win when only \n\
|
||||
one piece is left.\n";
|
||||
let measurement = measure_text(rules, None, font_size as u16, 1.0);
|
||||
draw_multiline_text(
|
||||
rules,
|
||||
self.board_rect.x + 0.05 * self.square_width,
|
||||
self.board_rect.y + 0.5 * (self.board_rect.h - measurement.height)
|
||||
- 2. * measurement.offset_y,
|
||||
font_size,
|
||||
Some(2.),
|
||||
UiColor::Brown.to_fg_color(),
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
let sprite_size = 0.8 * self.square_width;
|
||||
let mut selected_square = None;
|
||||
self.squares.iter().for_each(|square| {
|
||||
let color = if square.is_source {
|
||||
Color::from_rgba(112, 105, 141, 255)
|
||||
} else if square.is_target {
|
||||
Color::from_rgba(112, 150, 141, 255)
|
||||
} else {
|
||||
square.color
|
||||
let color = match square.is_source {
|
||||
true => square.color,
|
||||
false => match square.is_target {
|
||||
true => UiColor::Pink.to_shadow_color(),
|
||||
false => square.color,
|
||||
},
|
||||
};
|
||||
|
||||
draw_rectangle(
|
||||
@ -276,6 +346,10 @@ impl Game {
|
||||
for btn in &self.mode_btns {
|
||||
btn.1.draw();
|
||||
}
|
||||
|
||||
for btn in &self.rules_btn {
|
||||
btn.draw();
|
||||
}
|
||||
}
|
||||
|
||||
fn draw_debug(&self) {
|
||||
@ -310,6 +384,7 @@ impl Game {
|
||||
let board_width = self.square_width * self.num_squares as f32;
|
||||
let board_x = (self.window_width - board_width) / 2.0;
|
||||
let board_y = (self.window_height - board_width) / 2.0;
|
||||
self.board_rect = Rect::new(board_x, board_y, board_width, board_width);
|
||||
|
||||
self.heading_font_size = 0.07 * min_dimension;
|
||||
let f = self.heading_font_size.floor() as u16;
|
||||
@ -321,8 +396,8 @@ impl Game {
|
||||
dims.height,
|
||||
);
|
||||
|
||||
let dark = Color::from_rgba(83, 104, 120, 255);
|
||||
let light = Color::from_rgba(190, 190, 190, 255);
|
||||
let dark = UiColor::Brown.to_bg_color();
|
||||
let light = UiColor::Yellow.to_bg_color();
|
||||
let mut rects = Vec::new();
|
||||
for i in 0..self.num_squares {
|
||||
for j in 0..self.num_squares {
|
||||
@ -356,7 +431,7 @@ impl Game {
|
||||
let reset_btn = Button::new(
|
||||
"Reset",
|
||||
Rect::new(board_x + btn_x_offset, btn_y, btn_w, btn_h),
|
||||
ButtonColor::Red,
|
||||
UiColor::Yellow,
|
||||
);
|
||||
let mut next_btn = Button::new(
|
||||
"Next",
|
||||
@ -366,11 +441,22 @@ impl Game {
|
||||
btn_w,
|
||||
btn_h,
|
||||
),
|
||||
ButtonColor::Green,
|
||||
UiColor::Green,
|
||||
);
|
||||
|
||||
next_btn.is_active = false;
|
||||
|
||||
let rules_button = Button::new(
|
||||
"Rules",
|
||||
Rect::new(
|
||||
(board_x - btn_w) / 2.,
|
||||
board_y + (self.square_width - btn_h) / 2.,
|
||||
btn_w,
|
||||
btn_h,
|
||||
),
|
||||
UiColor::Brown,
|
||||
);
|
||||
self.rules_btn = vec![rules_button];
|
||||
|
||||
self.gp_btns = HashMap::new();
|
||||
self.gp_btns.insert(ButtonAction::Next, next_btn);
|
||||
self.gp_btns.insert(ButtonAction::Reset, reset_btn);
|
||||
@ -379,33 +465,33 @@ impl Game {
|
||||
"Easy",
|
||||
Rect::new(
|
||||
(board_x - btn_w) / 2.,
|
||||
board_y + (self.square_width - btn_h) / 2.,
|
||||
board_y + self.square_width + (self.square_width - btn_h) / 2.,
|
||||
btn_w,
|
||||
btn_h,
|
||||
),
|
||||
ButtonColor::Blue,
|
||||
UiColor::Yellow,
|
||||
);
|
||||
|
||||
let medium_btn = Button::new(
|
||||
"Medium",
|
||||
Rect::new(
|
||||
(board_x - btn_w) / 2.,
|
||||
board_y + self.square_width + (self.square_width - btn_h) / 2.,
|
||||
board_y + 2. * self.square_width + (self.square_width - btn_h) / 2.,
|
||||
btn_w,
|
||||
btn_h,
|
||||
),
|
||||
ButtonColor::Blue,
|
||||
UiColor::Yellow,
|
||||
);
|
||||
|
||||
let hard_button = Button::new(
|
||||
"Hard",
|
||||
Rect::new(
|
||||
(board_x - btn_w) / 2.,
|
||||
board_y + 2. * self.square_width + (self.square_width - btn_h) / 2.,
|
||||
board_y + 3. * self.square_width + (self.square_width - btn_h) / 2.,
|
||||
btn_w,
|
||||
btn_h,
|
||||
),
|
||||
ButtonColor::Blue,
|
||||
UiColor::Yellow,
|
||||
);
|
||||
|
||||
self.mode_btns = HashMap::new();
|
||||
|
@ -1,45 +1,19 @@
|
||||
use macroquad::prelude::*;
|
||||
|
||||
use super::{color::UiColor, shadow::draw_shadow};
|
||||
|
||||
pub struct Button {
|
||||
pub is_active: bool,
|
||||
text: String,
|
||||
pub text: String,
|
||||
is_down: bool,
|
||||
is_clicked: bool,
|
||||
rect: Rect,
|
||||
shadow_width: f32,
|
||||
color: ButtonColor,
|
||||
}
|
||||
|
||||
pub enum ButtonColor {
|
||||
Grey,
|
||||
Green,
|
||||
Red,
|
||||
Blue,
|
||||
}
|
||||
|
||||
impl ButtonColor {
|
||||
fn to_bg_color(&self) -> Color {
|
||||
match self {
|
||||
ButtonColor::Grey => Color::from_rgba(140, 140, 140, 200),
|
||||
ButtonColor::Green => Color::from_rgba(112, 140, 141, 200),
|
||||
ButtonColor::Red => Color::from_rgba(123, 70, 85, 200),
|
||||
ButtonColor::Blue => Color::from_rgba(140, 120, 250, 200),
|
||||
}
|
||||
}
|
||||
|
||||
fn to_shadow_color(&self) -> Color {
|
||||
let bg_color = self.to_bg_color();
|
||||
Color::from_rgba(
|
||||
(bg_color.r * 255.) as u8,
|
||||
(bg_color.g * 255.) as u8,
|
||||
(bg_color.b * 255.) as u8,
|
||||
100,
|
||||
)
|
||||
}
|
||||
pub color: UiColor,
|
||||
}
|
||||
|
||||
impl Button {
|
||||
pub fn new(text: &str, rect: Rect, color: ButtonColor) -> Self {
|
||||
pub fn new(text: &str, rect: Rect, color: UiColor) -> Self {
|
||||
Self {
|
||||
text: text.to_string(),
|
||||
is_down: false,
|
||||
@ -68,9 +42,8 @@ impl Button {
|
||||
fn draw_button(&self) {
|
||||
let bg_color = match self.is_active {
|
||||
true => self.color.to_bg_color(),
|
||||
false => ButtonColor::Grey.to_bg_color(),
|
||||
false => self.color.to_shadow_color(),
|
||||
};
|
||||
|
||||
let button_draw_offset = self.get_button_draw_offset();
|
||||
draw_rectangle(
|
||||
self.rect.x + button_draw_offset,
|
||||
@ -92,47 +65,12 @@ impl Button {
|
||||
return;
|
||||
}
|
||||
|
||||
let color = self.color.to_shadow_color();
|
||||
draw_rectangle(
|
||||
self.rect.x + self.rect.w,
|
||||
self.rect.y + self.shadow_width,
|
||||
self.shadow_width,
|
||||
self.rect.h,
|
||||
color,
|
||||
);
|
||||
|
||||
draw_rectangle(
|
||||
self.rect.x + self.shadow_width,
|
||||
self.rect.y + self.rect.h,
|
||||
self.rect.w - self.shadow_width,
|
||||
self.shadow_width,
|
||||
color,
|
||||
);
|
||||
|
||||
draw_triangle(
|
||||
vec2(self.rect.x + self.rect.w, self.rect.y),
|
||||
vec2(
|
||||
self.rect.x + self.rect.w + self.shadow_width,
|
||||
self.rect.y + self.shadow_width,
|
||||
),
|
||||
vec2(self.rect.x + self.rect.w, self.rect.y + self.shadow_width),
|
||||
color,
|
||||
);
|
||||
|
||||
draw_triangle(
|
||||
vec2(self.rect.x, self.rect.y + self.rect.h),
|
||||
vec2(
|
||||
self.rect.x + self.shadow_width,
|
||||
self.rect.y + self.rect.h + self.shadow_width,
|
||||
),
|
||||
vec2(self.rect.x + self.shadow_width, self.rect.y + self.rect.h),
|
||||
color,
|
||||
);
|
||||
draw_shadow(self.rect, self.shadow_width);
|
||||
}
|
||||
|
||||
fn draw_label(&self) {
|
||||
let font_color = match self.is_active {
|
||||
true => Color::from_rgba(0, 0, 0, 255),
|
||||
true => self.color.to_fg_color(),
|
||||
false => Color::from_rgba(100, 100, 100, 255),
|
||||
};
|
||||
|
||||
|
45
src/game/color.rs
Normal file
45
src/game/color.rs
Normal file
@ -0,0 +1,45 @@
|
||||
use macroquad::prelude::*;
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum UiColor {
|
||||
Grey,
|
||||
Green,
|
||||
Pink,
|
||||
Brown,
|
||||
Yellow,
|
||||
Blue,
|
||||
}
|
||||
|
||||
impl UiColor {
|
||||
pub fn to_bg_color(&self) -> Color {
|
||||
match self {
|
||||
UiColor::Grey => Color::from_rgba(140, 140, 140, 200),
|
||||
UiColor::Green => Color::from_rgba(16, 60, 50, 200),
|
||||
UiColor::Pink => Color::from_rgba(234, 128, 71, 200),
|
||||
UiColor::Brown => Color::from_rgba(123, 61, 35, 200),
|
||||
UiColor::Yellow => Color::from_rgba(242, 230, 190, 200),
|
||||
UiColor::Blue => Color::from_rgba(47, 85, 172, 200),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_fg_color(&self) -> Color {
|
||||
match self {
|
||||
UiColor::Grey => Color::from_rgba(255, 255, 255, 200),
|
||||
UiColor::Green => Color::from_rgba(255, 255, 255, 200),
|
||||
UiColor::Pink => Color::from_rgba(255, 255, 255, 200),
|
||||
UiColor::Brown => Color::from_rgba(255, 255, 255, 200),
|
||||
UiColor::Yellow => Color::from_rgba(0, 0, 0, 200),
|
||||
UiColor::Blue => Color::from_rgba(255, 255, 255, 200),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_shadow_color(&self) -> Color {
|
||||
let bg_color = self.to_bg_color();
|
||||
Color::from_rgba(
|
||||
(bg_color.r * 255.) as u8,
|
||||
(bg_color.g * 255.) as u8,
|
||||
(bg_color.b * 255.) as u8,
|
||||
100,
|
||||
)
|
||||
}
|
||||
}
|
20
src/game/shadow.rs
Normal file
20
src/game/shadow.rs
Normal file
@ -0,0 +1,20 @@
|
||||
use macroquad::prelude::*;
|
||||
|
||||
pub fn draw_shadow(rect: Rect, shadow_width: f32) {
|
||||
let shadow_color = Color::new(0., 0., 0., 0.8);
|
||||
draw_rectangle(
|
||||
rect.x + rect.w,
|
||||
rect.y + shadow_width,
|
||||
shadow_width,
|
||||
rect.h,
|
||||
shadow_color,
|
||||
);
|
||||
|
||||
draw_rectangle(
|
||||
rect.x + shadow_width,
|
||||
rect.y + rect.h,
|
||||
rect.w - shadow_width,
|
||||
shadow_width,
|
||||
shadow_color,
|
||||
);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user