Minesweeper-rs/src/main.rs
Alexander Bass 86dfecb4b3 init
2023-04-22 18:10:47 -04:00

197 lines
6 KiB
Rust

use gui::top_menu::smile::SmileyState;
use gui::ui_event::*;
use gui::{GameUI, UIState};
use logic::{events::GameEvent, Minesweeper};
use macroquad::{
prelude::*,
ui::{root_ui, Skin},
Window,
};
mod gui;
mod logic;
mod sprite_loader;
mod util;
fn main() {
let width = (30 * 32) as i32;
let height = (16 * 32) as i32 + 100;
Window::from_config(
Conf {
sample_count: 2,
window_title: String::from("Minesweeper"),
high_dpi: false,
window_width: width,
window_height: height,
..Default::default()
},
run(),
);
}
async fn run() {
let mut game_logic = Minesweeper::new(30, 16, 99).unwrap();
let top_buffer = 100; //px
let mut interface = GameUI::new(UIState::new(30, 16, 32, top_buffer));
let skin = {
let button_style = root_ui().style_builder().build();
let scrollbar_handle_style = root_ui().style_builder().build();
let window_style = root_ui().style_builder().color(Color::from_rgba(0, 0, 0, 0)).build();
Skin {
scroll_width: 0f32,
scrollbar_handle_style,
button_style,
window_style,
..root_ui().default_skin()
}
};
let settings_skin = {
let button_texture = Image::from_file_with_format(include_bytes!("../assets/button.png"), Some(ImageFormat::Png));
let button_clicked_texture =
Image::from_file_with_format(include_bytes!("../assets/button_clicked.png"), Some(ImageFormat::Png));
let label_style = root_ui().style_builder().font_size(20).build();
let button_style = root_ui()
.style_builder()
.font_size(20)
.background(button_texture)
.background_clicked(button_clicked_texture)
.build();
Skin {
scroll_width: 0f32,
button_style,
label_style,
..root_ui().default_skin()
}
};
let settings_skin_exit = {
let button_texture = Image::from_file_with_format(include_bytes!("../assets/exit_button.png"), Some(ImageFormat::Png));
let button_hover_texture =
Image::from_file_with_format(include_bytes!("../assets/exit_button_hover.png"), Some(ImageFormat::Png));
let button_style = root_ui()
.style_builder()
.background(button_texture)
.background_hovered(button_hover_texture)
.build();
Skin {
scroll_width: 0f32,
button_style,
..root_ui().default_skin()
}
};
let mut old_screen_size = (0.0, 0.0);
let background_color = Color::from_rgba(123, 123, 123, 255);
loop {
root_ui().push_skin(&skin);
clear_background(background_color);
while let Some(ge) = game_logic.events.next() {
match ge {
GameEvent::Lose(_, _, _) => {
interface.state.frozen = true;
interface.event_handler.add(GUIEvent::SetSmileyState(SmileyState::Dead));
interface.state.reveal_all = true;
}
GameEvent::Win => {
interface.state.frozen = true;
interface.event_handler.add(GUIEvent::SetSmileyState(SmileyState::Victory));
interface.state.reveal_all = true;
}
GameEvent::Reset => {
interface.clear();
}
_ => (),
}
}
{
let screen_width = screen_width();
let screen_height = screen_height();
// Only update letterboxing calculations when screen size changes
if (screen_width, screen_height) != old_screen_size {
interface.state.update_letterbox(screen_width, screen_height);
old_screen_size = (screen_width, screen_height);
}
let (mouse_x, mouse_y) = mouse_position();
let (min_x, min_y) = interface.state.pixel_screen_offset(10, 10 + interface.state.top_offset);
let tile_size = interface.state.tile_size;
let (max_x, max_y) = interface.state.pixel_screen_offset(
interface.state.width * tile_size - 10,
interface.state.height * tile_size + interface.state.top_offset - 10,
);
if mouse_x < min_x || mouse_y < min_y || mouse_x > max_x || mouse_y > max_y {
interface.state.mouse_in_minefield = false;
} else {
interface.state.mouse_in_minefield = true;
if let Some((x, y)) = interface.to_coordinate_system(
(mouse_x - interface.state.letterbox.0) / interface.state.scale,
(mouse_y - interface.state.letterbox.1) / interface.state.scale,
) {
interface.set_cursor(x, y);
}
}
if interface.state.settings_open {
interface.settings_menu.render(
&interface.state,
&mut interface.event_handler,
&interface.texture_store,
&settings_skin,
&settings_skin_exit,
);
} else {
interface.highlighter.events(&interface.state, &mut interface.event_handler, &mut game_logic.board);
interface.highlighter.highlight(&interface.state, &mut interface.event_handler);
game_logic.board.render(&interface.texture_store, &interface.state);
game_logic.board.events(&interface.state, &mut interface.event_handler);
interface.top_menu.render(
&interface.state,
&game_logic,
&mut interface.event_handler,
&interface.texture_store,
);
}
}
while let Some(ue) = interface.event_handler.next() {
match ue {
GUIEvent::ClickReset => {
game_logic.reset();
interface.state.mouse_in_minefield = false
}
GUIEvent::ClickTile(x, y) => {
game_logic.reveal(x, y);
}
GUIEvent::ModifyTile(x, y) => game_logic.modify(x, y),
GUIEvent::HighlightTile(x, y) => game_logic.highlight(x, y),
GUIEvent::UnHighlightTile(x, y) => game_logic.remove_highlight(x, y),
GUIEvent::OpenSettings => {
interface.state.mouse_in_minefield = false;
interface.state.frozen = true;
interface.state.settings_open = true;
}
GUIEvent::CloseSettings => {
interface.state.frozen = false;
interface.state.settings_open = false;
}
GUIEvent::SwitchLanguage(lang) => {
interface.state.language = lang;
interface.texture_store.lang = lang;
}
GUIEvent::CreateNewGame(width, height, mines) => {
interface.state.frozen = false;
interface.state.update_dimensions(width, height);
game_logic.update_and_reset(width, height, mines);
interface.state.update_letterbox(screen_width(), screen_height())
}
GUIEvent::SetQuestionMode(mode) => game_logic.board.modify_mode = mode,
GUIEvent::SetSmileyState(smiley_state) => interface.top_menu.smile.set_smile(smiley_state),
}
}
next_frame().await;
}
}