From 6e7313a509f0524211dc816e5199e21263eddedb Mon Sep 17 00:00:00 2001 From: Tobias Wennberg Date: Wed, 12 Mar 2025 17:37:49 +0100 Subject: [PATCH] Timer, refactor and more --- src/helpers.rs | 171 ++--------------------------- src/main.rs | 291 ++++++++++++++++++++++++++++++------------------- 2 files changed, 187 insertions(+), 275 deletions(-) diff --git a/src/helpers.rs b/src/helpers.rs index 6a0c3c7..fab82bb 100755 --- a/src/helpers.rs +++ b/src/helpers.rs @@ -6,13 +6,6 @@ pub struct RelatedMineIterator<'a> { inner: std::slice::Iter<'a, Option>, } -#[derive(PartialEq, Eq, Clone)] -pub enum BoxTypeBin { - Safe, - Mine, - Other, -} - impl<'a> Iterator for RelatedMineIterator<'a> { type Item = &'a Option; @@ -34,30 +27,6 @@ impl RelatedBoxes { self.dr.clone(), ] } - // recursive function to add open event to related boxes if it is zero - pub fn iterate_rel_mines( - &self, - commands: &mut Commands, - boxes: &mut Query<&mut Box>, - related_boxes: &Query<&RelatedBoxes>, - ) { - for related_box in self.iter() { - let box_entity = match related_box { - Some(b) => {b}, - None => {continue}, - }; - let mut r#box_val = boxes.get_mut(box_entity).unwrap(); - if box_val.0 != BoxType::Open { - continue - } - r#box_val.0 = BoxType::Open; - commands.entity(related_box.unwrap()).insert(BoxToOpen); - let related_box = related_boxes.get(box_entity).unwrap(); - if related_box.nearby_mines_count_box_mut(boxes) == 0 { -// related_box.iterate_rel_mines(draw_event, boxes, related_boxes) - } - } - } pub fn relates_with(&self, entity: Entity) -> bool { for rel_entity in self.iter() { if let Some(e) = rel_entity { @@ -70,12 +39,12 @@ impl RelatedBoxes { } pub fn nearby_box_unopened_count( &self, - boxes: &Query<&Box>, + opened_boxes: &Query<&OpenedBox>, ) -> usize { let mut i = 0; for ent in self.iter() { if let Some(e) = ent { - if !boxes.get(e).unwrap().is_opened() { + if !opened_boxes.contains(e) { i += 1; } } @@ -84,156 +53,30 @@ impl RelatedBoxes { } pub fn nearby_box_marked_count( &self, - boxes: &Query<&Box>, + boxes: &Query<&MarkedBox>, ) -> usize { let mut i = 0; for ent in self.iter() { if let Some(e) = ent { - if boxes.get(e).unwrap().is_marked() { + if boxes.contains(e) { i += 1; } } } return i; } - pub fn nearby_mines_count_box( + pub fn nearby_mines_count( &self, - boxes: &Query<&Box>, + mine_boxes: &Query<&MineBox>, ) -> usize { let mut i = 0; for ent in self.iter() { if let Some(e) = ent { - if boxes.get(e).unwrap().0.is_mine() { + if mine_boxes.contains(e) { i += 1; } } } return i; } - pub fn nearby_mines_count_box_mut( - &self, - boxes: &Query<&mut Box>, - ) -> usize { - let mut i = 0; - for ent in self.iter() { - if let Some(e) = ent { - if boxes.get(e).unwrap().0.is_mine() { - i += 1; - } - } - } - return i; - } - pub fn nearby_mines_count_no_hovered( - &self, - boxes: Query<&Box, Without>, - ) -> usize { - let mut i = 0; - for ent in self.iter() { - if let Some(e) = ent { - if boxes.get(e).unwrap().0.is_mine() { - i += 1; - } - } - } - return i; - } - -} -impl BoxType { - pub fn is_opened(&self) -> bool { - match self { - BoxType::Open => true, - BoxType::Safe => false, - BoxType::MarkedSafe => false, - BoxType::Mine => false, - BoxType::MarkedMine => false, - BoxType::OpenMine => true, - } - } - pub fn box_type_bin(&self) -> BoxTypeBin { - match self { - BoxType::Open => BoxTypeBin::Other, - BoxType::Safe => BoxTypeBin::Safe, - BoxType::MarkedSafe => BoxTypeBin::Other, - BoxType::Mine => BoxTypeBin::Mine, - BoxType::MarkedMine => BoxTypeBin::Other, - BoxType::OpenMine => BoxTypeBin::Other, - } - } - pub fn can_open(&self) -> bool { - match self { - BoxType::Open => false, - BoxType::Safe => true, - BoxType::MarkedSafe => false, - BoxType::Mine => true, - BoxType::MarkedMine => false, - BoxType::OpenMine => false, - } - } - pub fn is_mine(&self) -> bool { - match self { - BoxType::Open => false, - BoxType::Safe => false, - BoxType::MarkedSafe => false, - BoxType::Mine => true, - BoxType::MarkedMine => true, - BoxType::OpenMine => true, - } - } } -impl Box { - pub fn is_opened(&self) -> bool { - match &self.0 { - BoxType::Open => true, - BoxType::Safe => false, - BoxType::MarkedSafe => false, - BoxType::Mine => false, - BoxType::MarkedMine => false, - BoxType::OpenMine => true, - } - - } - pub fn is_marked(&self) -> bool { - match &self.0 { - BoxType::Open => false, - BoxType::Safe => false, - BoxType::MarkedSafe => true, - BoxType::Mine => false, - BoxType::MarkedMine => true, - BoxType::OpenMine => false, - } - - } - pub fn open(&self) -> Self { - match &self.0 { - BoxType::Open => Box(BoxType::Open), - BoxType::Safe => Box(BoxType::Open), - BoxType::MarkedSafe => Box(BoxType::MarkedSafe), - BoxType::Mine => Box(BoxType::OpenMine), - BoxType::MarkedMine =>Box(BoxType::MarkedMine), - BoxType::OpenMine => Box(BoxType::OpenMine), - } - } - pub fn mark(&self) -> Self { - match &self.0 { - BoxType::Open => (*self).clone(), - BoxType::Safe => Box(BoxType::MarkedSafe), - BoxType::MarkedSafe => Box(BoxType::MarkedSafe), - BoxType::Mine => Box(BoxType::MarkedMine), - BoxType::MarkedMine =>Box(BoxType::MarkedMine), - BoxType::OpenMine => Box(BoxType::OpenMine), - } - } - pub fn mark_flip(&self) -> Self { - match &self.0 { - BoxType::Open => (*self).clone(), - BoxType::Safe => Box(BoxType::MarkedSafe), - BoxType::MarkedSafe => Box(BoxType::Safe), - BoxType::Mine => Box(BoxType::MarkedMine), - BoxType::MarkedMine =>Box(BoxType::Mine), - BoxType::OpenMine => Box(BoxType::Mine), - } - } -} - diff --git a/src/main.rs b/src/main.rs index e8db093..4f0dfad 100755 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,6 @@ mod helpers; use rand::{rng, Rng}; -use bevy::prelude::*; +use bevy::{prelude::*, text::FontSmoothing, time::Stopwatch}; use bevy_pancam::*; const COLOR_OPEN_BOX: Color = Color::srgb(0.749, 0.749, 0.635); @@ -8,10 +8,14 @@ const COLOR_HIDDEN_BOX: Color = Color::srgb(0.459, 0.459, 0.408); const COLOR_MARKED_BOX: Color = Color::srgb(0.769, 0.435, 0.043); const COLOR_OPEN_MINE: Color = Color::srgb(1., 0., 0.); -const BOARD_WIDTH :usize = 16; -const BOARD_HEIGHT :usize = 30; -const NUMER_OF_MINES :usize = 99; +const BOARD_WIDTH :usize = 9; +const BOARD_HEIGHT :usize = 9; +const NUMER_OF_MINES :usize = 10; +#[derive(Component)] +struct GameStopwatch(Stopwatch); + +// Actions #[derive(Component)] struct BoxToMarkFlip; #[derive(Component)] @@ -19,14 +23,23 @@ struct BoxToMark; #[derive(Component)] struct BoxToOpen; +// Box States #[derive(Component)] -struct SafeUnopenedBox; +struct OpenedBox; +#[derive(Component)] +struct MineBox; +#[derive(Component)] +struct MarkedBox; #[derive(Component)] -struct Hovered; +struct Box; + +#[derive(Component)] +struct HoveredBox; #[derive(States, Default, Clone, PartialEq, Eq, Hash, Debug)] enum GameState { + StartUi, #[default] Start, Playing, @@ -34,19 +47,6 @@ enum GameState { Fail, } -#[derive(Default, Reflect, Clone, PartialEq, Eq)] -enum BoxType { - Open, - #[default] - Safe, - MarkedSafe, - Mine, - MarkedMine, - OpenMine, -} - - - #[derive(Component, Clone, Copy)] struct RelatedBoxes { ul: Option, @@ -60,8 +60,6 @@ struct RelatedBoxes { } -#[derive(Default, Reflect, Component, Clone)] -struct Box(BoxType); #[derive(Resource)] @@ -78,93 +76,168 @@ fn main() { .insert_resource(MouseWorldCoordinate(None)) .insert_resource(BoxMatrix([[None; BOARD_WIDTH]; BOARD_HEIGHT])) .insert_state(GameState::Start) - .add_systems(Startup, (draw_boxes, init_camera)) + .add_systems(Startup, ( + load_initial_entities, + init_camera + )) .add_systems(PreUpdate, (mouse_world_pos, mark_hovered_box)) - .add_systems(Update, (init_mines).run_if(in_state(GameState::Start)).run_if(any_with_component::)) + .add_systems(Update, (init_mines).run_if(in_state(GameState::Start)).run_if(any_with_component::)) .add_systems(Update, ( - (handle_box).run_if(in_state(GameState::Playing)).run_if(any_with_component::), + ( + handle_box, + game_stopwatch, + switch_to_win, + ).run_if(in_state(GameState::Playing)).run_if(any_with_component::), open_box, mark_box, markflip_box, - switch_to_win, )) + .add_systems(OnEnter(GameState::Start), (despawn_boxes.before(draw_boxes), draw_boxes)) .add_systems(OnEnter(GameState::Fail), draw_fail) .add_systems(OnEnter(GameState::Win), draw_win) .run(); } +fn despawn_boxes( + mut commands: Commands, + boxes: Query>, +) { + for e in boxes.iter() { + commands.entity(e).despawn(); + } +} + + +fn load_initial_entities( + mut commands: Commands, +) { + commands.spawn(( + // Accepts a `String` or any type that converts into a `String`, such as `&str` + Text::new("0"), + TextFont { + font_size: 20., + ..default() + }, + TextColor(Color::srgb(0.,1.,1.)), + Node { + position_type: PositionType::Absolute, + top: Val::Percent(0.), + right: Val::Percent(50.), + ..default() + }, + GameStopwatch(Stopwatch::new()), + )); + +} + +fn game_stopwatch( + mut game_stopwatch: Query<(&mut GameStopwatch, &mut Text)>, + time: Res