Timer, refactor and more
This commit is contained in:
parent
9517b89479
commit
6e7313a509
171
src/helpers.rs
171
src/helpers.rs
@ -6,13 +6,6 @@ pub struct RelatedMineIterator<'a> {
|
|||||||
inner: std::slice::Iter<'a, Option<Entity>>,
|
inner: std::slice::Iter<'a, Option<Entity>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(PartialEq, Eq, Clone)]
|
|
||||||
pub enum BoxTypeBin {
|
|
||||||
Safe,
|
|
||||||
Mine,
|
|
||||||
Other,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> Iterator for RelatedMineIterator<'a> {
|
impl<'a> Iterator for RelatedMineIterator<'a> {
|
||||||
type Item = &'a Option<Entity>;
|
type Item = &'a Option<Entity>;
|
||||||
|
|
||||||
@ -34,30 +27,6 @@ impl RelatedBoxes {
|
|||||||
self.dr.clone(),
|
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 {
|
pub fn relates_with(&self, entity: Entity) -> bool {
|
||||||
for rel_entity in self.iter() {
|
for rel_entity in self.iter() {
|
||||||
if let Some(e) = rel_entity {
|
if let Some(e) = rel_entity {
|
||||||
@ -70,12 +39,12 @@ impl RelatedBoxes {
|
|||||||
}
|
}
|
||||||
pub fn nearby_box_unopened_count(
|
pub fn nearby_box_unopened_count(
|
||||||
&self,
|
&self,
|
||||||
boxes: &Query<&Box>,
|
opened_boxes: &Query<&OpenedBox>,
|
||||||
) -> usize {
|
) -> usize {
|
||||||
let mut i = 0;
|
let mut i = 0;
|
||||||
for ent in self.iter() {
|
for ent in self.iter() {
|
||||||
if let Some(e) = ent {
|
if let Some(e) = ent {
|
||||||
if !boxes.get(e).unwrap().is_opened() {
|
if !opened_boxes.contains(e) {
|
||||||
i += 1;
|
i += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -84,156 +53,30 @@ impl RelatedBoxes {
|
|||||||
}
|
}
|
||||||
pub fn nearby_box_marked_count(
|
pub fn nearby_box_marked_count(
|
||||||
&self,
|
&self,
|
||||||
boxes: &Query<&Box>,
|
boxes: &Query<&MarkedBox>,
|
||||||
) -> usize {
|
) -> usize {
|
||||||
let mut i = 0;
|
let mut i = 0;
|
||||||
for ent in self.iter() {
|
for ent in self.iter() {
|
||||||
if let Some(e) = ent {
|
if let Some(e) = ent {
|
||||||
if boxes.get(e).unwrap().is_marked() {
|
if boxes.contains(e) {
|
||||||
i += 1;
|
i += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
pub fn nearby_mines_count_box(
|
pub fn nearby_mines_count(
|
||||||
&self,
|
&self,
|
||||||
boxes: &Query<&Box>,
|
mine_boxes: &Query<&MineBox>,
|
||||||
) -> usize {
|
) -> usize {
|
||||||
let mut i = 0;
|
let mut i = 0;
|
||||||
for ent in self.iter() {
|
for ent in self.iter() {
|
||||||
if let Some(e) = ent {
|
if let Some(e) = ent {
|
||||||
if boxes.get(e).unwrap().0.is_mine() {
|
if mine_boxes.contains(e) {
|
||||||
i += 1;
|
i += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return i;
|
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<Hovered>>,
|
|
||||||
) -> 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),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|||||||
293
src/main.rs
293
src/main.rs
@ -1,6 +1,6 @@
|
|||||||
mod helpers;
|
mod helpers;
|
||||||
use rand::{rng, Rng};
|
use rand::{rng, Rng};
|
||||||
use bevy::prelude::*;
|
use bevy::{prelude::*, text::FontSmoothing, time::Stopwatch};
|
||||||
use bevy_pancam::*;
|
use bevy_pancam::*;
|
||||||
|
|
||||||
const COLOR_OPEN_BOX: Color = Color::srgb(0.749, 0.749, 0.635);
|
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_MARKED_BOX: Color = Color::srgb(0.769, 0.435, 0.043);
|
||||||
const COLOR_OPEN_MINE: Color = Color::srgb(1., 0., 0.);
|
const COLOR_OPEN_MINE: Color = Color::srgb(1., 0., 0.);
|
||||||
|
|
||||||
const BOARD_WIDTH :usize = 16;
|
const BOARD_WIDTH :usize = 9;
|
||||||
const BOARD_HEIGHT :usize = 30;
|
const BOARD_HEIGHT :usize = 9;
|
||||||
const NUMER_OF_MINES :usize = 99;
|
const NUMER_OF_MINES :usize = 10;
|
||||||
|
|
||||||
|
#[derive(Component)]
|
||||||
|
struct GameStopwatch(Stopwatch);
|
||||||
|
|
||||||
|
// Actions
|
||||||
#[derive(Component)]
|
#[derive(Component)]
|
||||||
struct BoxToMarkFlip;
|
struct BoxToMarkFlip;
|
||||||
#[derive(Component)]
|
#[derive(Component)]
|
||||||
@ -19,14 +23,23 @@ struct BoxToMark;
|
|||||||
#[derive(Component)]
|
#[derive(Component)]
|
||||||
struct BoxToOpen;
|
struct BoxToOpen;
|
||||||
|
|
||||||
|
// Box States
|
||||||
#[derive(Component)]
|
#[derive(Component)]
|
||||||
struct SafeUnopenedBox;
|
struct OpenedBox;
|
||||||
|
#[derive(Component)]
|
||||||
|
struct MineBox;
|
||||||
|
#[derive(Component)]
|
||||||
|
struct MarkedBox;
|
||||||
|
|
||||||
#[derive(Component)]
|
#[derive(Component)]
|
||||||
struct Hovered;
|
struct Box;
|
||||||
|
|
||||||
|
#[derive(Component)]
|
||||||
|
struct HoveredBox;
|
||||||
|
|
||||||
#[derive(States, Default, Clone, PartialEq, Eq, Hash, Debug)]
|
#[derive(States, Default, Clone, PartialEq, Eq, Hash, Debug)]
|
||||||
enum GameState {
|
enum GameState {
|
||||||
|
StartUi,
|
||||||
#[default]
|
#[default]
|
||||||
Start,
|
Start,
|
||||||
Playing,
|
Playing,
|
||||||
@ -34,19 +47,6 @@ enum GameState {
|
|||||||
Fail,
|
Fail,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default, Reflect, Clone, PartialEq, Eq)]
|
|
||||||
enum BoxType {
|
|
||||||
Open,
|
|
||||||
#[default]
|
|
||||||
Safe,
|
|
||||||
MarkedSafe,
|
|
||||||
Mine,
|
|
||||||
MarkedMine,
|
|
||||||
OpenMine,
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#[derive(Component, Clone, Copy)]
|
#[derive(Component, Clone, Copy)]
|
||||||
struct RelatedBoxes {
|
struct RelatedBoxes {
|
||||||
ul: Option<Entity>,
|
ul: Option<Entity>,
|
||||||
@ -60,8 +60,6 @@ struct RelatedBoxes {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#[derive(Default, Reflect, Component, Clone)]
|
|
||||||
struct Box(BoxType);
|
|
||||||
|
|
||||||
|
|
||||||
#[derive(Resource)]
|
#[derive(Resource)]
|
||||||
@ -78,93 +76,168 @@ fn main() {
|
|||||||
.insert_resource(MouseWorldCoordinate(None))
|
.insert_resource(MouseWorldCoordinate(None))
|
||||||
.insert_resource(BoxMatrix([[None; BOARD_WIDTH]; BOARD_HEIGHT]))
|
.insert_resource(BoxMatrix([[None; BOARD_WIDTH]; BOARD_HEIGHT]))
|
||||||
.insert_state(GameState::Start)
|
.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(PreUpdate, (mouse_world_pos, mark_hovered_box))
|
||||||
.add_systems(Update, (init_mines).run_if(in_state(GameState::Start)).run_if(any_with_component::<Hovered>))
|
.add_systems(Update, (init_mines).run_if(in_state(GameState::Start)).run_if(any_with_component::<HoveredBox>))
|
||||||
.add_systems(Update, (
|
.add_systems(Update, (
|
||||||
(handle_box).run_if(in_state(GameState::Playing)).run_if(any_with_component::<Hovered>),
|
(
|
||||||
|
handle_box,
|
||||||
|
game_stopwatch,
|
||||||
|
switch_to_win,
|
||||||
|
).run_if(in_state(GameState::Playing)).run_if(any_with_component::<HoveredBox>),
|
||||||
open_box,
|
open_box,
|
||||||
mark_box,
|
mark_box,
|
||||||
markflip_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::Fail), draw_fail)
|
||||||
.add_systems(OnEnter(GameState::Win), draw_win)
|
.add_systems(OnEnter(GameState::Win), draw_win)
|
||||||
.run();
|
.run();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn despawn_boxes(
|
||||||
|
mut commands: Commands,
|
||||||
|
boxes: Query<Entity, With<Box>>,
|
||||||
|
) {
|
||||||
|
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<Time>,
|
||||||
|
) {
|
||||||
|
let (mut stopwatch, mut text) = game_stopwatch.single_mut();
|
||||||
|
stopwatch.0.tick(time.delta());
|
||||||
|
let seconds = stopwatch.0.elapsed().as_secs_f64();
|
||||||
|
text.0 = format!("T: {:.3}s", seconds);
|
||||||
|
}
|
||||||
|
|
||||||
fn switch_to_win(
|
fn switch_to_win(
|
||||||
mut next_state: ResMut<NextState<GameState>>,
|
mut next_state: ResMut<NextState<GameState>>,
|
||||||
unopened_safes: Query<&SafeUnopenedBox>
|
opened_safes: Query<&OpenedBox, Without<MineBox>>,
|
||||||
) {
|
) {
|
||||||
if !unopened_safes.is_empty() {
|
if opened_safes.iter().count() != (BOARD_WIDTH*BOARD_HEIGHT - NUMER_OF_MINES) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
next_state.set(GameState::Win);
|
next_state.set(GameState::Win);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn draw_win(
|
fn draw_win(
|
||||||
mut commands: Commands
|
mut commands: Commands,
|
||||||
|
mut game_stopwatch: Query<&mut GameStopwatch>,
|
||||||
) {
|
) {
|
||||||
commands.spawn(Text2d::new("WIN!!"));
|
let mut stopwatch = game_stopwatch.single_mut();
|
||||||
|
stopwatch.0.pause();
|
||||||
|
commands.spawn((
|
||||||
|
// Accepts a `String` or any type that converts into a `String`, such as `&str`
|
||||||
|
Text::new("WIN!!"),
|
||||||
|
TextFont {
|
||||||
|
font_size: 200.,
|
||||||
|
..default()
|
||||||
|
},
|
||||||
|
TextColor(Color::srgb(0.,1.,1.)),
|
||||||
|
Node {
|
||||||
|
position_type: PositionType::Absolute,
|
||||||
|
bottom: Val::Percent(50.),
|
||||||
|
right: Val::Percent(50.),
|
||||||
|
..default()
|
||||||
|
},
|
||||||
|
));
|
||||||
}
|
}
|
||||||
fn draw_fail(
|
fn draw_fail(
|
||||||
mut commands: Commands
|
mut commands: Commands,
|
||||||
|
mut game_stopwatch: Query<&mut GameStopwatch>,
|
||||||
|
mut next_state: ResMut<NextState<GameState>>,
|
||||||
) {
|
) {
|
||||||
commands.spawn(Text2d::new("FAIL!!"));
|
let mut stopwatch = game_stopwatch.single_mut();
|
||||||
|
stopwatch.0.pause();
|
||||||
|
commands.spawn((
|
||||||
|
// Accepts a `String` or any type that converts into a `String`, such as `&str`
|
||||||
|
Text::new("FAIL!"),
|
||||||
|
TextFont {
|
||||||
|
font_size: 200.,
|
||||||
|
..default()
|
||||||
|
},
|
||||||
|
TextColor(Color::srgb(1.,0.,0.)),
|
||||||
|
Node {
|
||||||
|
position_type: PositionType::Absolute,
|
||||||
|
bottom: Val::Percent(50.),
|
||||||
|
right: Val::Percent(50.),
|
||||||
|
..default()
|
||||||
|
},
|
||||||
|
));
|
||||||
|
next_state.set(GameState::Start);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn markflip_box(
|
fn markflip_box(
|
||||||
mut commands: Commands,
|
mut commands: Commands,
|
||||||
box_entity_to_open: Query<Entity, With<BoxToMarkFlip>>,
|
box_entity_to_open: Query<Entity, With<BoxToMarkFlip>>,
|
||||||
mut boxes: Query<&mut Box>,
|
box_marked: Query<&MarkedBox>,
|
||||||
mut color_material: Query<&mut MeshMaterial2d<ColorMaterial>>,
|
mut color_material: Query<&mut MeshMaterial2d<ColorMaterial>>,
|
||||||
mut materials: ResMut<Assets<ColorMaterial>>,
|
mut materials: ResMut<Assets<ColorMaterial>>,
|
||||||
) {
|
) {
|
||||||
for entity in box_entity_to_open.iter() {
|
for entity in box_entity_to_open.iter() {
|
||||||
println!("FLIP");
|
|
||||||
commands.entity(entity).remove::<BoxToMarkFlip>();
|
commands.entity(entity).remove::<BoxToMarkFlip>();
|
||||||
let mut r#box = boxes.get_mut(entity).unwrap();
|
let is_marked = box_marked.contains(entity);
|
||||||
*r#box = r#box.mark_flip();
|
*color_material.get_mut(entity).unwrap() = match is_marked {
|
||||||
let mut r#material = color_material.get_mut(entity).unwrap();
|
true => {
|
||||||
*r#material = match r#box.0 {
|
commands.entity(entity).remove::<(BoxToMarkFlip, MarkedBox)>();
|
||||||
BoxType::Open => MeshMaterial2d(materials.add(COLOR_OPEN_BOX)),
|
MeshMaterial2d(materials.add(COLOR_HIDDEN_BOX))
|
||||||
BoxType::Safe => MeshMaterial2d(materials.add(COLOR_HIDDEN_BOX)),
|
},
|
||||||
BoxType::MarkedSafe => MeshMaterial2d(materials.add(COLOR_MARKED_BOX)),
|
false => {
|
||||||
BoxType::Mine => MeshMaterial2d(materials.add(COLOR_HIDDEN_BOX)),
|
commands.entity(entity).remove::<BoxToMarkFlip>().insert(MarkedBox);
|
||||||
BoxType::MarkedMine => MeshMaterial2d(materials.add(COLOR_MARKED_BOX)),
|
MeshMaterial2d(materials.add(COLOR_MARKED_BOX))
|
||||||
BoxType::OpenMine => MeshMaterial2d(materials.add(COLOR_OPEN_MINE)),
|
},
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn mark_box(
|
fn mark_box(
|
||||||
mut commands: Commands,
|
mut commands: Commands,
|
||||||
box_entity_to_open: Query<Entity, With<BoxToMark>>,
|
box_entity_to_open: Query<Entity, (With<BoxToMark>, Without<OpenedBox>)>,
|
||||||
mut boxes: Query<&mut Box>,
|
|
||||||
mut color_material: Query<&mut MeshMaterial2d<ColorMaterial>>,
|
mut color_material: Query<&mut MeshMaterial2d<ColorMaterial>>,
|
||||||
mut materials: ResMut<Assets<ColorMaterial>>,
|
mut materials: ResMut<Assets<ColorMaterial>>,
|
||||||
) {
|
) {
|
||||||
for entity in box_entity_to_open.iter() {
|
for entity in box_entity_to_open.iter() {
|
||||||
commands.entity(entity).remove::<BoxToMark>();
|
commands.entity(entity).remove::<BoxToMark>();
|
||||||
let mut r#box = boxes.get_mut(entity).unwrap();
|
commands.entity(entity).insert(MarkedBox);
|
||||||
*r#box = r#box.mark();
|
*color_material.get_mut(entity).unwrap() = MeshMaterial2d(materials.add(COLOR_MARKED_BOX));
|
||||||
let mut r#material = color_material.get_mut(entity).unwrap();
|
|
||||||
*r#material = match r#box.0 {
|
|
||||||
BoxType::Open => MeshMaterial2d(materials.add(COLOR_OPEN_BOX)),
|
|
||||||
BoxType::Safe => MeshMaterial2d(materials.add(COLOR_HIDDEN_BOX)),
|
|
||||||
BoxType::MarkedSafe => MeshMaterial2d(materials.add(COLOR_MARKED_BOX)),
|
|
||||||
BoxType::Mine => MeshMaterial2d(materials.add(COLOR_HIDDEN_BOX)),
|
|
||||||
BoxType::MarkedMine => MeshMaterial2d(materials.add(COLOR_MARKED_BOX)),
|
|
||||||
BoxType::OpenMine => MeshMaterial2d(materials.add(COLOR_OPEN_MINE)),
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn open_box(
|
fn open_box(
|
||||||
mut commands: Commands,
|
mut commands: Commands,
|
||||||
box_entity_to_open: Query<Entity, With<BoxToOpen>>,
|
box_entity_to_open: Query<Entity, (With<BoxToOpen>, Without<OpenedBox>)>,
|
||||||
mut boxes: Query<&mut Box>,
|
marked_boxes: Query<&MarkedBox>,
|
||||||
|
mine_boxes: Query<&MineBox>,
|
||||||
|
safe_opened_boxes: Query<&OpenedBox, Without<MineBox>>,
|
||||||
related_boxes: Query<&RelatedBoxes>,
|
related_boxes: Query<&RelatedBoxes>,
|
||||||
transforms: Query<&Transform>,
|
|
||||||
mut color_material: Query<&mut MeshMaterial2d<ColorMaterial>>,
|
mut color_material: Query<&mut MeshMaterial2d<ColorMaterial>>,
|
||||||
mut materials: ResMut<Assets<ColorMaterial>>,
|
mut materials: ResMut<Assets<ColorMaterial>>,
|
||||||
mut next_state: ResMut<NextState<GameState>>,
|
mut next_state: ResMut<NextState<GameState>>,
|
||||||
@ -181,49 +254,39 @@ fn open_box(
|
|||||||
let entity = boxes_to_open[counter];
|
let entity = boxes_to_open[counter];
|
||||||
counter += 1;
|
counter += 1;
|
||||||
commands.entity(entity).remove::<BoxToOpen>();
|
commands.entity(entity).remove::<BoxToOpen>();
|
||||||
let mut r#box = boxes.get_mut(entity).unwrap();
|
if marked_boxes.contains(entity) {
|
||||||
if !r#box.0.can_open() {
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
*r#box = r#box.open();
|
commands.entity(entity).insert(OpenedBox);
|
||||||
commands.entity(entity).remove::<SafeUnopenedBox>();
|
|
||||||
if r#box.0 == BoxType::OpenMine {
|
|
||||||
next_state.set(GameState::Fail);
|
|
||||||
}
|
|
||||||
let mut r#material = color_material.get_mut(entity).unwrap();
|
let mut r#material = color_material.get_mut(entity).unwrap();
|
||||||
*r#material = match r#box.0 {
|
if mine_boxes.contains(entity) {
|
||||||
BoxType::Open => MeshMaterial2d(materials.add(COLOR_OPEN_BOX)),
|
next_state.set(GameState::Fail);
|
||||||
BoxType::Safe => MeshMaterial2d(materials.add(COLOR_HIDDEN_BOX)),
|
*r#material = MeshMaterial2d(materials.add(COLOR_OPEN_MINE));
|
||||||
BoxType::MarkedSafe => MeshMaterial2d(materials.add(COLOR_MARKED_BOX)),
|
return
|
||||||
BoxType::Mine => MeshMaterial2d(materials.add(COLOR_HIDDEN_BOX)),
|
}
|
||||||
BoxType::MarkedMine => MeshMaterial2d(materials.add(COLOR_MARKED_BOX)),
|
*r#material = MeshMaterial2d(materials.add(COLOR_OPEN_BOX));
|
||||||
BoxType::OpenMine => MeshMaterial2d(materials.add(COLOR_OPEN_MINE)),
|
let related_boxes = related_boxes.get(entity).unwrap();
|
||||||
};
|
let rel_mine_count = related_boxes.nearby_mines_count(&mine_boxes);
|
||||||
let rel_mine = related_boxes.get(entity).unwrap();
|
let text_entity = commands.spawn((
|
||||||
let rel_mine_count = rel_mine.nearby_mines_count_box_mut(&boxes);
|
|
||||||
let transform = transforms.get(entity).unwrap();
|
|
||||||
commands.spawn((
|
|
||||||
Text2d::new( if rel_mine_count != 0 { rel_mine_count.to_string() } else {"".to_string()}),
|
Text2d::new( if rel_mine_count != 0 { rel_mine_count.to_string() } else {"".to_string()}),
|
||||||
TextLayout::new_with_justify(JustifyText::Center),
|
Transform::default().with_scale(Vec3::new(0.3,0.3,0.)),
|
||||||
transform.clone().with_scale(Vec3::new(0.3,0.3,0.)),
|
)).id();
|
||||||
));
|
commands.entity(entity).add_child(text_entity);
|
||||||
if rel_mine_count != 0 {
|
if rel_mine_count != 0 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
for related_box in rel_mine.iter() {
|
for related_box in related_boxes.iter() {
|
||||||
let box_entity = match related_box {
|
let box_entity = match related_box {
|
||||||
Some(b) => {b},
|
Some(b) => {b},
|
||||||
None => {continue},
|
None => {continue},
|
||||||
};
|
};
|
||||||
let box_val = boxes.get(box_entity).unwrap();
|
if safe_opened_boxes.contains(box_entity) {
|
||||||
if box_val.0 == BoxType::Open {
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if boxes_to_open.contains(&related_box.unwrap()) {
|
if boxes_to_open.contains(&related_box.unwrap()) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
boxes_to_open.push(related_box.unwrap());
|
boxes_to_open.push(related_box.unwrap());
|
||||||
//commands.entity(related_box.unwrap()).insert(BoxToOpen);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -231,33 +294,38 @@ fn open_box(
|
|||||||
fn init_mines(
|
fn init_mines(
|
||||||
mut commands: Commands,
|
mut commands: Commands,
|
||||||
mouse_button_input: Res<ButtonInput<MouseButton>>,
|
mouse_button_input: Res<ButtonInput<MouseButton>>,
|
||||||
mut boxes: Query<(Entity, &mut Box)>,
|
mine_boxes: Query<&MineBox>,
|
||||||
mut hovered_box: Query<(Entity, &RelatedBoxes), With<Hovered>>,
|
mut hovered_box: Query<(Entity, &RelatedBoxes), With<HoveredBox>>,
|
||||||
mut next_state: ResMut<NextState<GameState>>,
|
mut next_state: ResMut<NextState<GameState>>,
|
||||||
box_matrix: Res<BoxMatrix>,
|
box_matrix: Res<BoxMatrix>,
|
||||||
|
mut game_stopwatch: Query<&mut GameStopwatch>,
|
||||||
) {
|
) {
|
||||||
let _mouse_key = if mouse_button_input.just_pressed(MouseButton::Left) { MouseButton::Left }
|
let _mouse_key = if mouse_button_input.just_pressed(MouseButton::Left) || mouse_button_input.just_pressed(MouseButton::Right) { MouseButton::Left }
|
||||||
else {return};
|
else {return};
|
||||||
|
|
||||||
let (hovered_entity, rel_mine) = hovered_box.single_mut();
|
let (hovered_entity, rel_mine) = hovered_box.single_mut();
|
||||||
commands.entity(hovered_entity).insert(BoxToOpen);
|
commands.entity(hovered_entity).insert(BoxToOpen);
|
||||||
let mut number_of_mines = 0;
|
let mut number_of_mines = 0;
|
||||||
while number_of_mines <= NUMER_OF_MINES {
|
'main: loop {
|
||||||
for i in 0..box_matrix.0.len() {
|
for i in 0..box_matrix.0.len() {
|
||||||
for j in 0..box_matrix.0[i].len() {
|
for j in 0..box_matrix.0[i].len() {
|
||||||
let (entity, mut r#box) = boxes.get_mut(box_matrix.0[i][j].unwrap()).unwrap();
|
let entity = box_matrix.0[i][j].unwrap();
|
||||||
if entity == hovered_entity || rel_mine.relates_with(entity) {
|
if entity == hovered_entity || rel_mine.relates_with(entity) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if r#box.0 != BoxType::Mine {
|
if !mine_boxes.contains(entity) {
|
||||||
r#box.0 = match random_bool(NUMER_OF_MINES as f64 / (BOARD_WIDTH*BOARD_HEIGHT) as f64) {
|
if random_bool(NUMER_OF_MINES as f64 / (BOARD_WIDTH*BOARD_HEIGHT) as f64) {
|
||||||
true => { number_of_mines += 1; commands.entity(entity).remove::<SafeUnopenedBox>(); BoxType::Mine},
|
number_of_mines += 1;
|
||||||
false => BoxType::Safe,
|
commands.entity(entity).insert(MineBox);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
if number_of_mines >= NUMER_OF_MINES {
|
||||||
|
break 'main
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
game_stopwatch.single_mut().0.reset();
|
||||||
next_state.set(GameState::Playing);
|
next_state.set(GameState::Playing);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -268,8 +336,8 @@ fn draw_boxes(
|
|||||||
mut box_matrix: ResMut<BoxMatrix>,
|
mut box_matrix: ResMut<BoxMatrix>,
|
||||||
) {
|
) {
|
||||||
let rec = meshes.add(Rectangle::new(5., 5.));
|
let rec = meshes.add(Rectangle::new(5., 5.));
|
||||||
let offset_x = 6.;
|
let offset_x = 5.9;
|
||||||
let offset_y = 6.;
|
let offset_y = 5.9;
|
||||||
let mut matrix: [[Option<Entity>; BOARD_WIDTH]; BOARD_HEIGHT] = [[None; BOARD_WIDTH]; BOARD_HEIGHT];
|
let mut matrix: [[Option<Entity>; BOARD_WIDTH]; BOARD_HEIGHT] = [[None; BOARD_WIDTH]; BOARD_HEIGHT];
|
||||||
|
|
||||||
for i in 0..BOARD_HEIGHT {
|
for i in 0..BOARD_HEIGHT {
|
||||||
@ -280,8 +348,7 @@ fn draw_boxes(
|
|||||||
Mesh2d(rec.clone()),
|
Mesh2d(rec.clone()),
|
||||||
MeshMaterial2d(materials.add(COLOR_HIDDEN_BOX)),
|
MeshMaterial2d(materials.add(COLOR_HIDDEN_BOX)),
|
||||||
Transform::from_xyz(x, y, 0.),
|
Transform::from_xyz(x, y, 0.),
|
||||||
Box::default(),
|
Box,
|
||||||
SafeUnopenedBox
|
|
||||||
)
|
)
|
||||||
).id());
|
).id());
|
||||||
}
|
}
|
||||||
@ -332,8 +399,11 @@ fn mark_hovered_box(
|
|||||||
mut commands: Commands,
|
mut commands: Commands,
|
||||||
mouse_world: Res<MouseWorldCoordinate>,
|
mouse_world: Res<MouseWorldCoordinate>,
|
||||||
mut boxes: Query<(Entity, &Transform), With<Box>>,
|
mut boxes: Query<(Entity, &Transform), With<Box>>,
|
||||||
prev_hovered: Query<Entity, With<Hovered>>,
|
prev_hovered: Query<Entity, With<HoveredBox>>,
|
||||||
) {
|
) {
|
||||||
|
for e in prev_hovered.iter() {
|
||||||
|
commands.entity(e).remove::<HoveredBox>();
|
||||||
|
}
|
||||||
let mouse = match mouse_world.0 {
|
let mouse = match mouse_world.0 {
|
||||||
Some(x) => {x},
|
Some(x) => {x},
|
||||||
None => return,
|
None => return,
|
||||||
@ -347,25 +417,24 @@ fn mark_hovered_box(
|
|||||||
Some(s) => {s},
|
Some(s) => {s},
|
||||||
None => {return},
|
None => {return},
|
||||||
};
|
};
|
||||||
for e in prev_hovered.iter() {
|
commands.entity(entity).insert(HoveredBox);
|
||||||
commands.entity(e).remove::<Hovered>();
|
|
||||||
}
|
|
||||||
commands.entity(entity).insert(Hovered);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_box(
|
fn handle_box(
|
||||||
mut commands: Commands,
|
mut commands: Commands,
|
||||||
mouse_button_input: Res<ButtonInput<MouseButton>>,
|
mouse_button_input: Res<ButtonInput<MouseButton>>,
|
||||||
hovered_boxes: Query<(Entity, &Box), With<Hovered>>,
|
hovered_boxes: Query<Entity, With<HoveredBox>>,
|
||||||
boxes: Query<&Box>,
|
opened_boxes: Query<&OpenedBox>,
|
||||||
|
mine_boxes: Query<&MineBox>,
|
||||||
|
marked_boxes: Query<&MarkedBox>,
|
||||||
related_boxes: Query<&RelatedBoxes>,
|
related_boxes: Query<&RelatedBoxes>,
|
||||||
) {
|
) {
|
||||||
|
|
||||||
let mouse_key = if mouse_button_input.just_pressed(MouseButton::Left) { MouseButton::Left }
|
let mouse_key = if mouse_button_input.just_pressed(MouseButton::Left) { MouseButton::Left }
|
||||||
else if mouse_button_input.just_pressed(MouseButton::Right) {MouseButton::Right}
|
else if mouse_button_input.just_pressed(MouseButton::Right) {MouseButton::Right}
|
||||||
else {return};
|
else {return};
|
||||||
let (entity, r#box) = hovered_boxes.get_single().unwrap();
|
let entity = hovered_boxes.get_single().unwrap();
|
||||||
if !r#box.0.is_opened() {
|
if !opened_boxes.contains(entity) {
|
||||||
match mouse_key {
|
match mouse_key {
|
||||||
MouseButton::Left => {
|
MouseButton::Left => {
|
||||||
commands.entity(entity).insert(BoxToOpen);
|
commands.entity(entity).insert(BoxToOpen);
|
||||||
@ -377,9 +446,9 @@ fn handle_box(
|
|||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
let rel_box = related_boxes.get(entity).unwrap();
|
let rel_box = related_boxes.get(entity).unwrap();
|
||||||
let box_count = rel_box.nearby_mines_count_box(&boxes);
|
let box_count = rel_box.nearby_mines_count(&mine_boxes);
|
||||||
let rel_box_marked_count = rel_box.nearby_box_marked_count(&boxes);
|
let rel_box_marked_count = rel_box.nearby_box_marked_count(&marked_boxes);
|
||||||
let rel_box_unopened_count = rel_box.nearby_box_unopened_count(&boxes);
|
let rel_box_unopened_count = rel_box.nearby_box_unopened_count(&opened_boxes);
|
||||||
if rel_box_marked_count == box_count {
|
if rel_box_marked_count == box_count {
|
||||||
for rel_box in rel_box.iter() {
|
for rel_box in rel_box.iter() {
|
||||||
if let Some(e) = rel_box {
|
if let Some(e) = rel_box {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user