Add difficulty levels

This commit is contained in:
cool-mist 2025-05-18 00:09:11 +05:30
parent 373d3da91b
commit d90e270cd5
3 changed files with 108 additions and 27 deletions

View File

@ -31,12 +31,12 @@ pub struct Game {
// Constants througout the game // Constants througout the game
texture_res: Texture2D, texture_res: Texture2D,
num_squares: usize, num_squares: usize,
heading_font_size: f32,
heading_text: String, heading_text: String,
// Update below on handle input // Update below on handle input
state: GameState, state: GameState,
debug: bool, debug: bool,
game_mode: GameMode,
// Update below on window resize // Update below on window resize
// Used for drawing the state // Used for drawing the state
@ -45,7 +45,9 @@ pub struct Game {
window_width: f32, window_width: f32,
squares: Vec<GameSquare>, squares: Vec<GameSquare>,
heading_rect: Rect, heading_rect: Rect,
btns: HashMap<ButtonAction, Button>, heading_font_size: f32,
gp_btns: HashMap<ButtonAction, Button>,
mode_btns: HashMap<GameMode, Button>,
} }
struct GameSquare { struct GameSquare {
@ -64,6 +66,13 @@ pub enum ButtonAction {
Next, Next,
} }
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
pub enum GameMode {
Easy,
Medium,
Hard,
}
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
enum GameState { enum GameState {
SelectSource(Option<(usize, usize)>), SelectSource(Option<(usize, usize)>),
@ -72,8 +81,10 @@ enum GameState {
} }
impl Game { impl Game {
pub fn new(board: Board, texture_res: Texture2D) -> Self { pub fn new(texture_res: Texture2D) -> Self {
let num_squares: usize = 4; let num_squares: usize = 4;
let game_mode = GameMode::Medium;
let board = Game::generate_puzzle(game_mode);
Self { Self {
original_board: board.clone(), original_board: board.clone(),
@ -85,24 +96,27 @@ impl Game {
num_squares, num_squares,
texture_res, texture_res,
state: GameState::SelectSource(None), state: GameState::SelectSource(None),
game_mode,
debug: false, debug: false,
btns: HashMap::new(), gp_btns: HashMap::new(),
mode_btns: HashMap::new(),
window_height: 0., window_height: 0.,
window_width: 0., window_width: 0.,
square_width: 0., square_width: 0.,
} }
} }
pub fn draw(&self) { pub fn draw(&mut self) {
self.update_window_size();
self.draw_heading(); self.draw_heading();
self.draw_board(); self.draw_board();
self.draw_buttons(); self.draw_buttons();
self.draw_debug(); self.draw_debug();
} }
pub fn update_window_size(&mut self) { fn update_window_size(&mut self) {
let new_height = math::clamp(screen_height(), 100.0, 10000.0); let new_height = math::clamp(screen_height(), 200.0, 10000.0);
let new_width = math::clamp(screen_width(), 100.0, 10000.0); let new_width = math::clamp(screen_width(), 200.0, 10000.0);
if new_height == self.window_height && new_width == self.window_width { if new_height == self.window_height && new_width == self.window_width {
return; return;
} }
@ -114,7 +128,7 @@ impl Game {
pub fn handle_input(&mut self) { pub fn handle_input(&mut self) {
let mut btn_clicked = None; let mut btn_clicked = None;
for btn in &mut self.btns { for btn in &mut self.gp_btns {
btn.1.handle_input(); btn.1.handle_input();
if btn.1.is_clicked() { if btn.1.is_clicked() {
btn_clicked = Some(btn.0.clone()); btn_clicked = Some(btn.0.clone());
@ -127,6 +141,23 @@ impl Game {
ButtonAction::Reset => self.reset(), ButtonAction::Reset => self.reset(),
ButtonAction::Next => self.next_puzzle(), ButtonAction::Next => self.next_puzzle(),
} }
} else {
for btn in &mut self.mode_btns {
btn.1.handle_input();
if btn.1.is_clicked() {
self.game_mode = *btn.0;
self.next_puzzle();
break;
}
}
}
for btn in &mut self.mode_btns {
if self.game_mode == *btn.0 {
btn.1.is_active = false;
} else {
btn.1.is_active = true;
}
} }
if is_key_released(KeyCode::D) { if is_key_released(KeyCode::D) {
@ -238,7 +269,11 @@ impl Game {
} }
fn draw_buttons(&self) { fn draw_buttons(&self) {
for btn in &self.btns { for btn in &self.gp_btns {
btn.1.draw();
}
for btn in &self.mode_btns {
btn.1.draw(); btn.1.draw();
} }
} }
@ -313,7 +348,7 @@ impl Game {
self.squares = rects; self.squares = rects;
let btn_h = 0.08 * self.window_height; let btn_h = 0.08 * min_dimension;
let btn_w = board_width * 0.2; let btn_w = board_width * 0.2;
let btn_y = board_width + board_y + 0.3 * self.square_width; let btn_y = board_width + board_y + 0.3 * self.square_width;
@ -321,7 +356,7 @@ impl Game {
let reset_btn = Button::new( let reset_btn = Button::new(
"Reset", "Reset",
Rect::new(board_x + btn_x_offset, btn_y, btn_w, btn_h), Rect::new(board_x + btn_x_offset, btn_y, btn_w, btn_h),
ButtonColor::Yellow, ButtonColor::Red,
); );
let mut next_btn = Button::new( let mut next_btn = Button::new(
"Next", "Next",
@ -336,9 +371,49 @@ impl Game {
next_btn.is_active = false; next_btn.is_active = false;
self.btns = HashMap::new(); self.gp_btns = HashMap::new();
self.btns.insert(ButtonAction::Next, next_btn); self.gp_btns.insert(ButtonAction::Next, next_btn);
self.btns.insert(ButtonAction::Reset, reset_btn); self.gp_btns.insert(ButtonAction::Reset, reset_btn);
let easy_btn = Button::new(
"Easy",
Rect::new((board_x - btn_w) / 2., (board_y + btn_h) / 2., btn_w, btn_h),
ButtonColor::Grey,
);
let medium_btn = Button::new(
"Medium",
Rect::new(
(board_x - btn_w) / 2.,
(board_y + board_width) / 2.,
btn_w,
btn_h,
),
ButtonColor::Grey,
);
let hard_button = Button::new(
"Hard",
Rect::new(
(board_x - btn_w) / 2.,
(board_y + board_width),
btn_w,
btn_h,
),
ButtonColor::Grey,
);
self.mode_btns = HashMap::new();
self.mode_btns.insert(GameMode::Easy, easy_btn);
self.mode_btns.insert(GameMode::Medium, medium_btn);
self.mode_btns.insert(GameMode::Hard, hard_button);
for btn in &mut self.mode_btns {
btn.1.is_active = true;
if self.game_mode == *btn.0 {
btn.1.is_active = false;
}
}
} }
fn handle_select_source( fn handle_select_source(
@ -428,7 +503,7 @@ impl Game {
self.reset_squares(); self.reset_squares();
if self.board.game_state == BoardState::Won { if self.board.game_state == BoardState::Won {
let next_btn = self let next_btn = self
.btns .gp_btns
.get_mut(&ButtonAction::Next) .get_mut(&ButtonAction::Next)
.expect("Cannot find next button"); .expect("Cannot find next button");
next_btn.is_active = true; next_btn.is_active = true;
@ -451,7 +526,7 @@ impl Game {
self.reset_squares(); self.reset_squares();
let next_button = self let next_button = self
.btns .gp_btns
.get_mut(&ButtonAction::Next) .get_mut(&ButtonAction::Next)
.expect("Cannot find next button"); .expect("Cannot find next button");
next_button.is_active = false; next_button.is_active = false;
@ -461,8 +536,7 @@ impl Game {
fn next_puzzle(&mut self) { fn next_puzzle(&mut self) {
self.reset(); self.reset();
let generate = generator::generate(6, 100, &MacroquadRandAdapter); let board = Game::generate_puzzle(self.game_mode);
let board = generate.board().expect("No puzzle was generated");
self.original_board = board.clone(); self.original_board = board.clone();
self.board = board; self.board = board;
} }
@ -494,6 +568,17 @@ impl Game {
BLACK, BLACK,
); );
} }
fn generate_puzzle(mode: GameMode) -> Board {
let piece_count = match mode {
GameMode::Easy => 3,
GameMode::Medium => 5,
GameMode::Hard => 7,
};
let generate = generator::generate(piece_count, 100, &MacroquadRandAdapter);
generate.board().expect("No puzzle was generated")
}
} }
impl Display for GameState { impl Display for GameState {

View File

@ -13,7 +13,7 @@ pub struct Button {
pub enum ButtonColor { pub enum ButtonColor {
Grey, Grey,
Green, Green,
Yellow, Red,
} }
impl ButtonColor { impl ButtonColor {
@ -21,7 +21,7 @@ impl ButtonColor {
match self { match self {
ButtonColor::Grey => Color::from_rgba(140, 140, 140, 200), ButtonColor::Grey => Color::from_rgba(140, 140, 140, 200),
ButtonColor::Green => Color::from_rgba(112, 140, 141, 200), ButtonColor::Green => Color::from_rgba(112, 140, 141, 200),
ButtonColor::Yellow => Color::from_rgba(123, 70, 85, 200), ButtonColor::Red => Color::from_rgba(123, 70, 85, 200),
} }
} }

View File

@ -1,7 +1,6 @@
use game::{Game, MacroquadRandAdapter}; use game::Game;
use macroquad::prelude::*; use macroquad::prelude::*;
use miniquad::date; use miniquad::date;
use sol_chess::generator;
mod game; mod game;
@ -26,7 +25,6 @@ async fn main() {
loop { loop {
clear_background(background_color); clear_background(background_color);
game.handle_input(); game.handle_input();
game.update_window_size();
game.draw(); game.draw();
next_frame().await next_frame().await
} }
@ -37,9 +35,7 @@ async fn init() -> Game {
let texture_res = Texture2D::from_file_with_format(&texture_bytes[..], None); let texture_res = Texture2D::from_file_with_format(&texture_bytes[..], None);
texture_res.set_filter(FilterMode::Nearest); texture_res.set_filter(FilterMode::Nearest);
build_textures_atlas(); build_textures_atlas();
let generate = generator::generate(6, 100, &MacroquadRandAdapter); let game = Game::new(texture_res);
let board = generate.board().expect("No puzzle was generated");
let game = Game::new(board, texture_res);
game game
} }