unify event queues with Generics

This commit is contained in:
Alexander Bass 2023-06-06 13:13:55 -04:00
parent 761b9ba295
commit 993f608cfa
12 changed files with 95 additions and 115 deletions

View file

@ -4,10 +4,14 @@ pub mod settings_menu;
pub mod texture_store; pub mod texture_store;
mod tile_render; mod tile_render;
pub mod top_menu; pub mod top_menu;
pub mod ui_event;
use crate::{logic::game_board::ModifyMode, util::Events};
use self::{ use self::{
highlighter::Highlighter, settings_menu::SettingsMenu, texture_store::TextureStore, top_menu::GUITop, ui_event::GUIEvents, highlighter::Highlighter,
settings_menu::SettingsMenu,
texture_store::TextureStore,
top_menu::{smile::SmileyState, GUITop},
}; };
use macroquad::prelude::*; use macroquad::prelude::*;
#[derive(Default, Copy, Clone, Debug)] #[derive(Default, Copy, Clone, Debug)]
@ -16,6 +20,21 @@ pub enum Language {
English, English,
Japanese, Japanese,
} }
pub enum GUIEvent {
ClickReset,
OpenSettings,
CloseSettings,
SwitchLanguage(Language),
ClickTile(usize, usize),
ModifyTile(usize, usize),
HighlightTile(usize, usize),
UnHighlightTile(usize, usize),
CreateNewGame(usize, usize, usize),
SetQuestionMode(ModifyMode),
SetSmileyState(SmileyState),
}
#[derive(Debug, Default)] #[derive(Debug, Default)]
pub struct UIState { pub struct UIState {
pub width: usize, pub width: usize,
@ -85,7 +104,7 @@ impl UIState {
#[derive(Default)] #[derive(Default)]
pub struct GameUI { pub struct GameUI {
pub event_handler: GUIEvents, pub event_handler: Events<GUIEvent>,
pub highlighter: Highlighter, pub highlighter: Highlighter,
pub state: UIState, pub state: UIState,
pub settings_menu: SettingsMenu, pub settings_menu: SettingsMenu,

View file

@ -1,7 +1,7 @@
use crate::logic::game_board::GameBoard; use crate::{logic::game_board::GameBoard, util::Events};
use macroquad::prelude::*; use macroquad::prelude::*;
use super::{texture_store::TextureStore, ui_event::GUIEvents, UIState}; use super::{texture_store::TextureStore, GUIEvent, UIState};
impl GameBoard { impl GameBoard {
pub fn render(&self, textures: &TextureStore, settings: &UIState) { pub fn render(&self, textures: &TextureStore, settings: &UIState) {
// dbg!(&settings.top_offset, &settings.render_scale); // dbg!(&settings.top_offset, &settings.render_scale);
@ -32,13 +32,13 @@ impl GameBoard {
} }
} }
} }
pub fn events(&self, settings: &UIState, event_handler: &mut GUIEvents) { pub fn events(&self, settings: &UIState, event_handler: &mut Events<GUIEvent>) {
if settings.mouse_in_minefield && !settings.frozen { if settings.mouse_in_minefield && !settings.frozen {
if is_mouse_button_released(MouseButton::Left) { if is_mouse_button_released(MouseButton::Left) {
event_handler.add(super::ui_event::GUIEvent::ClickTile(settings.cursor.0, settings.cursor.1)) event_handler.add(GUIEvent::ClickTile(settings.cursor.0, settings.cursor.1))
} }
if is_mouse_button_released(MouseButton::Right) { if is_mouse_button_released(MouseButton::Right) {
event_handler.add(super::ui_event::GUIEvent::ModifyTile(settings.cursor.0, settings.cursor.1)) event_handler.add(GUIEvent::ModifyTile(settings.cursor.0, settings.cursor.1))
} }
} }
} }

View file

@ -5,10 +5,11 @@ use crate::{
game_board::GameBoard, game_board::GameBoard,
tile::{TileModifier, TileState}, tile::{TileModifier, TileState},
}, },
util::Events,
util::{ADJACENT_WITHOUT_CENTER, ADJACENT_WITH_CENTER}, util::{ADJACENT_WITHOUT_CENTER, ADJACENT_WITH_CENTER},
}; };
use super::{top_menu::smile::SmileyState, ui_event::GUIEvent, ui_event::GUIEvents, UIState}; use super::{top_menu::smile::SmileyState, GUIEvent, UIState};
use macroquad::prelude::*; use macroquad::prelude::*;
use std::default; use std::default;
@ -26,7 +27,7 @@ pub enum Highlight {
} }
impl Highlighter { impl Highlighter {
pub fn events(&mut self, ui_state: &UIState, event_handler: &mut GUIEvents, game_board: &mut GameBoard) { pub fn events(&mut self, ui_state: &UIState, event_handler: &mut Events<GUIEvent>, game_board: &mut GameBoard) {
if !ui_state.frozen && ui_state.mouse_in_minefield { if !ui_state.frozen && ui_state.mouse_in_minefield {
if is_mouse_button_pressed(MouseButton::Left) { if is_mouse_button_pressed(MouseButton::Left) {
self.highlight = Highlight::Normal; self.highlight = Highlight::Normal;
@ -49,7 +50,7 @@ impl Highlighter {
} }
} }
} }
fn check_reveal(&self, event_handler: &mut GUIEvents, interface: &UIState, game_board: &mut GameBoard) { fn check_reveal(&self, event_handler: &mut Events<GUIEvent>, interface: &UIState, game_board: &mut GameBoard) {
let (x, y) = interface.cursor; let (x, y) = interface.cursor;
if let Some(tile) = game_board.get_tile_mut(x, y) { if let Some(tile) = game_board.get_tile_mut(x, y) {
let adjacent_mines = tile.adjacent; let adjacent_mines = tile.adjacent;
@ -87,7 +88,7 @@ impl Highlighter {
} }
} }
} }
pub fn highlight(&mut self, interface: &UIState, event_handler: &mut GUIEvents) { pub fn highlight(&mut self, interface: &UIState, event_handler: &mut Events<GUIEvent>) {
if interface.frozen { if interface.frozen {
return; return;
} }
@ -119,7 +120,7 @@ impl Highlighter {
self.move_highlight(&interface, event_handler); self.move_highlight(&interface, event_handler);
} }
fn move_highlight(&mut self, interface: &UIState, event_handler: &mut GUIEvents) { fn move_highlight(&mut self, interface: &UIState, event_handler: &mut Events<GUIEvent>) {
if let Some((old_x, old_y)) = self.cursor_old { if let Some((old_x, old_y)) = self.cursor_old {
match self.highlight { match self.highlight {
Highlight::None => (), Highlight::None => (),
@ -165,7 +166,7 @@ impl Highlighter {
self.cursor_old = Some(interface.cursor); self.cursor_old = Some(interface.cursor);
} }
fn reset_highlight(&mut self, interface: &UIState, event_handler: &mut GUIEvents) { fn reset_highlight(&mut self, interface: &UIState, event_handler: &mut Events<GUIEvent>) {
if let Some((x, y)) = self.cursor_old { if let Some((x, y)) = self.cursor_old {
match self.highlight { match self.highlight {
Highlight::None => (), Highlight::None => (),

View file

@ -1,10 +1,6 @@
use crate::logic::game_board::ModifyMode; use crate::{logic::game_board::ModifyMode, util::Events};
use super::{ use super::{texture_store::TextureStore, GUIEvent, Language, UIState};
texture_store::TextureStore,
ui_event::{GUIEvent, GUIEvents},
Language, UIState,
};
use macroquad::{ use macroquad::{
hash, hash,
prelude::*, prelude::*,
@ -32,7 +28,7 @@ impl SettingsMenu {
pub fn render( pub fn render(
&mut self, &mut self,
ui_state: &UIState, ui_state: &UIState,
event_handler: &mut GUIEvents, event_handler: &mut Events<GUIEvent>,
textures: &TextureStore, textures: &TextureStore,
skin: &Skin, skin: &Skin,
exit_button_skin: &Skin, exit_button_skin: &Skin,
@ -53,7 +49,7 @@ impl SettingsMenu {
const MIN_MINEFIELD_WIDTH: usize = 5; const MIN_MINEFIELD_WIDTH: usize = 5;
const MAX_MINEFIELD_WIDTH: usize = 100; const MAX_MINEFIELD_WIDTH: usize = 100;
const MIN_MINEFIELD_HEIGHT: usize = 5; const MIN_MINEFIELD_HEIGHT: usize = 5;
const MAX_MINEFIELD_HEIGHT: usize = 100; // const MAX_MINEFIELD_HEIGHT: usize = 100;
render_counter( render_counter(
&mut self.width, &mut self.width,
ui, ui,

View file

@ -7,15 +7,11 @@ pub mod flag_counter;
pub mod smile; pub mod smile;
pub mod timer; pub mod timer;
use crate::logic::Minesweeper; use crate::{gui::GUIEvent, logic::Minesweeper, util::Events};
use self::{flag_counter::GUIFlagCounter, smile::GUISmile, timer::GUITimer}; use self::{flag_counter::GUIFlagCounter, smile::GUISmile, timer::GUITimer};
use super::{ use super::{texture_store::TextureStore, UIState};
texture_store::TextureStore,
ui_event::{GUIEvent, GUIEvents},
UIState,
};
use macroquad::prelude::*; use macroquad::prelude::*;
#[derive(Default)] #[derive(Default)]
pub struct GUITop { pub struct GUITop {
@ -29,7 +25,7 @@ impl GUITop {
&mut self, &mut self,
ui_state: &UIState, ui_state: &UIState,
game_logic: &Minesweeper, game_logic: &Minesweeper,
event_handler: &mut GUIEvents, event_handler: &mut Events<GUIEvent>,
textures: &TextureStore, textures: &TextureStore,
) { ) {
let background_color = Color::from_rgba(192, 192, 192, 255); let background_color = Color::from_rgba(192, 192, 192, 255);

View file

@ -3,9 +3,9 @@ use macroquad::{
ui::{widgets, Ui}, ui::{widgets, Ui},
}; };
use crate::gui::{ use crate::{
texture_store::TextureStore, gui::{texture_store::TextureStore, GUIEvent},
ui_event::{GUIEvent, GUIEvents}, util::Events,
}; };
use super::UIState; use super::UIState;
@ -34,7 +34,7 @@ const WIDTH: usize = 70;
const HEIGHT: usize = 70; const HEIGHT: usize = 70;
impl GUISmile { impl GUISmile {
pub fn render(&mut self, ui_state: &UIState, ui: &mut Ui, event_handler: &mut GUIEvents, textures: &TextureStore) { pub fn render(&mut self, ui_state: &UIState, ui: &mut Ui, event_handler: &mut Events<GUIEvent>, textures: &TextureStore) {
let top_height = ui_state.top_offset; let top_height = ui_state.top_offset;
let top_width = ui_state.width * ui_state.tile_size; let top_width = ui_state.width * ui_state.tile_size;
let pos_x = (top_width - HEIGHT) / 2; let pos_x = (top_width - HEIGHT) / 2;

View file

@ -1,37 +0,0 @@
use crate::logic::game_board::ModifyMode;
use super::{top_menu::smile::SmileyState, Language};
pub enum GUIEvent {
ClickReset,
OpenSettings,
CloseSettings,
SwitchLanguage(Language),
ClickTile(usize, usize),
ModifyTile(usize, usize),
HighlightTile(usize, usize),
UnHighlightTile(usize, usize),
CreateNewGame(usize, usize, usize),
SetQuestionMode(ModifyMode),
SetSmileyState(SmileyState),
}
#[derive(Default)]
pub struct GUIEvents {
events: Vec<GUIEvent>,
}
impl GUIEvents {
pub fn add(&mut self, event: GUIEvent) {
self.events.push(event);
}
pub fn next(&mut self) -> Option<GUIEvent> {
if self.events.len() > 0 {
self.events.pop()
} else {
None
}
}
pub fn clear(&mut self) {
self.events.clear();
}
}

View file

@ -1,11 +1,10 @@
pub mod events; // pub mod events;
pub mod game_board; pub mod game_board;
pub mod tile; pub mod tile;
mod timer; mod timer;
use self::{ use crate::util::Events;
events::{Events, GameEvent},
timer::Timer, use self::{tile::Tile, timer::Timer};
};
use game_board::GameBoard; use game_board::GameBoard;
use std::error::Error; use std::error::Error;
@ -17,13 +16,25 @@ pub enum GameState {
GameOver, GameOver,
Victory, Victory,
} }
pub enum GameEvent {
Lose(usize, usize, Tile),
RevealTile(usize, usize, Tile),
FlagTile(usize, usize, Tile),
QuestionTile(usize, usize, Tile),
SweepDone,
SweepBegin,
InitDone,
Win,
Reset,
GameEnd(GameBoard),
}
#[derive(Default)] #[derive(Default)]
pub struct Minesweeper { pub struct Minesweeper {
pub board: GameBoard, pub board: GameBoard,
pub events: Events<GameEvent>,
pub state: GameState, pub state: GameState,
timer: Timer, timer: Timer,
pub events: Events,
} }
impl Minesweeper { impl Minesweeper {

View file

@ -1,34 +0,0 @@
use super::game_board::GameBoard;
use super::tile::Tile;
pub enum GameEvent {
Lose(usize, usize, Tile),
RevealTile(usize, usize, Tile),
FlagTile(usize, usize, Tile),
QuestionTile(usize, usize, Tile),
SweepDone,
SweepBegin,
InitDone,
Win,
Reset,
GameEnd(GameBoard),
}
#[derive(Default)]
pub struct Events {
events: Vec<GameEvent>,
}
impl Events {
pub fn add(&mut self, event: GameEvent) {
self.events.push(event);
}
pub fn next(&mut self) -> Option<GameEvent> {
if self.events.len() > 0 {
self.events.pop()
} else {
None
}
}
pub fn clear(&mut self) {
self.events.clear();
}
}

View file

@ -98,7 +98,7 @@ impl GameBoard {
self.mines as isize - self.flags as isize self.mines as isize - self.flags as isize
} }
pub fn modify(&mut self, x: usize, y: usize, event_handler: &mut Events) { pub fn modify(&mut self, x: usize, y: usize, event_handler: &mut Events<GameEvent>) {
if let Some(&tile) = &self.get_tile(x, y) { if let Some(&tile) = &self.get_tile(x, y) {
if tile.swept { if tile.swept {
return; return;
@ -132,7 +132,7 @@ impl GameBoard {
} }
} }
pub fn sweep(&mut self, x: usize, y: usize, event_handler: &mut Events) -> Option<GameState> { pub fn sweep(&mut self, x: usize, y: usize, event_handler: &mut Events<GameEvent>) -> Option<GameState> {
if let BoardState::Ungenerated = self.state { if let BoardState::Ungenerated = self.state {
self.generate(x, y); self.generate(x, y);
} }

View file

@ -1,7 +1,6 @@
use gui::top_menu::smile::SmileyState; use gui::top_menu::smile::SmileyState;
use gui::ui_event::*; use gui::{GUIEvent, GameUI, UIState};
use gui::{GameUI, UIState}; use logic::{GameEvent, Minesweeper};
use logic::{events::GameEvent, Minesweeper};
use macroquad::{ use macroquad::{
prelude::*, prelude::*,
ui::{root_ui, Skin}, ui::{root_ui, Skin},

View file

@ -2,3 +2,32 @@ pub const ADJACENT_WITH_CENTER: [(isize, isize); 9] =
[(-1, -1), (0, -1), (1, -1), (-1, 0), (0, 0), (1, 0), (-1, 1), (0, 1), (1, 1)]; [(-1, -1), (0, -1), (1, -1), (-1, 0), (0, 0), (1, 0), (-1, 1), (0, 1), (1, 1)];
pub const ADJACENT_WITHOUT_CENTER: [(isize, isize); 8] = [(-1, -1), (0, -1), (1, -1), (-1, 0), (1, 0), (-1, 1), (0, 1), (1, 1)]; pub const ADJACENT_WITHOUT_CENTER: [(isize, isize); 8] = [(-1, -1), (0, -1), (1, -1), (-1, 0), (1, 0), (-1, 1), (0, 1), (1, 1)];
// Event Queue
pub struct Events<E> {
events: Vec<E>,
}
impl<E> Events<E> {
pub fn add(&mut self, event: E) {
self.events.push(event);
}
pub fn next(&mut self) -> Option<E> {
if self.events.len() > 0 {
self.events.pop()
} else {
None
}
}
pub fn clear(&mut self) {
self.events.clear();
}
}
impl<E> Default for Events<E> {
fn default() -> Self {
Self {
events: Vec::<E>::with_capacity(10),
}
}
}