Skip to content

Commit

Permalink
Implement NextPieceHint::Modern that will display next 5 pieces.
Browse files Browse the repository at this point in the history
  • Loading branch information
Ramirisu committed Sep 24, 2024
1 parent 686e96b commit 264237c
Show file tree
Hide file tree
Showing 6 changed files with 170 additions and 93 deletions.
27 changes: 16 additions & 11 deletions src/game/board.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use std::collections::VecDeque;

use super::{
piece::{Piece, Square},
rand::PieceRandomizer,
Expand All @@ -12,7 +14,7 @@ pub struct Board {
squares: Vec<Vec<Piece>>,
curr_piece: Piece,
curr_pos: (i32, i32),
next_piece: Piece,
next_pieces: VecDeque<Piece>,
lines: usize,
score: usize,
single: usize,
Expand All @@ -33,15 +35,18 @@ impl Board {

pub fn new(start_level: usize, transition: Transition) -> Self {
let randomizer = PieceRandomizer::System;
let next_piece = randomizer.gen();
let next_pieces = (0..5).fold(VecDeque::new(), |mut accu, _| {
accu.push_back(randomizer.gen_1h2r(&accu));
accu
});
let mut board = Self {
start_level,
transition,
randomizer,
squares: vec![vec![Piece::default(); Self::BOARD_COLS]; Self::BOARD_ROWS],
curr_piece: Piece::X,
curr_pos: (Self::BOARD_PIECE_START_X, Self::BOARD_PIECE_START_Y),
next_piece: next_piece,
next_pieces,
lines: 0,
score: 0,
single: 0,
Expand All @@ -53,7 +58,7 @@ impl Board {
piece_count: [0; Piece::variant_len()],
};

// auto apply `drought` and `rand_1h2r`
// auto apply `drought` and `curr_piece`
board.switch_to_next_piece();
board
}
Expand Down Expand Up @@ -155,19 +160,19 @@ impl Board {
}

pub fn switch_to_next_piece(&mut self) {
self.curr_piece = std::mem::replace(
&mut self.next_piece,
self.randomizer.gen_1h2r(self.curr_piece),
);
self.next_pieces
.push_back(self.randomizer.gen_1h2r(&self.next_pieces));
self.curr_piece = self.next_pieces.pop_front().unwrap();

self.curr_pos = (Self::BOARD_PIECE_START_X, Self::BOARD_PIECE_START_Y);
self.piece_count[self.curr_piece.variant_index()] += 1;
match self.curr_piece {
Piece::I(_) => self.drought = 0,
_ => {
self.drought += 1;
self.max_drought = self.max_drought.max(self.drought);
}
}
self.piece_count[self.curr_piece.variant_index()] += 1;
}

pub fn get_curr_piece(&self) -> Piece {
Expand All @@ -180,8 +185,8 @@ impl Board {
.map(|sqr| Square(sqr.0 + self.curr_pos.0, sqr.1 + self.curr_pos.1))
}

pub fn get_next_piece(&self) -> Piece {
self.next_piece
pub fn get_next_pieces(&self) -> &VecDeque<Piece> {
&self.next_pieces
}

pub fn is_left_movable(&self) -> bool {
Expand Down
19 changes: 12 additions & 7 deletions src/game/next_piece_hint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ use num_traits::FromPrimitive;
pub enum NextPieceHint {
Off,
#[default]
One,
Classic, // 1
Modern, // 5
}

impl NextPieceHint {
Expand All @@ -16,13 +17,17 @@ impl NextPieceHint {
pub fn enum_next(&mut self) -> Option<Self> {
FromPrimitive::from_i8(*self as i8 + 1).map(|n| std::mem::replace(self, n))
}
}

impl Into<Visibility> for NextPieceHint {
fn into(self) -> Visibility {
match self {
NextPieceHint::Off => Visibility::Hidden,
NextPieceHint::One => Visibility::Inherited,
pub fn get_visibility(&self, index: usize) -> Visibility {
let visible = match self {
NextPieceHint::Off => 0,
NextPieceHint::Classic => 1,
NextPieceHint::Modern => 5,
};
if index >= visible {
Visibility::Hidden
} else {
Visibility::Inherited
}
}
}
114 changes: 71 additions & 43 deletions src/game/plugin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ struct PieceCountCounterEntityMarker(Piece);
struct CurrPieceEntityMarker;

#[derive(Component)]
struct NextPieceEntityMarker;
struct NextPieceEntityMarker(usize);

fn load_square_image_assets(
mut commands: Commands,
Expand Down Expand Up @@ -425,57 +425,80 @@ fn setup_screen(
));
});

commands.spawn((
SpriteBundle {
transform: Transform::from_translation(
game_transform.next_piece_slot_background_translation(),
),
sprite: Sprite {
color: RED.into(),
custom_size: Some(game_transform.next_piece_slot_background_size()),
..default()
},
..default()
},
GameEntityMarker,
));
commands.spawn((
SpriteBundle {
transform: Transform::from_translation(game_transform.next_piece_slot_translation()),
sprite: Sprite {
color: BLACK.into(),
custom_size: Some(game_transform.next_piece_slot_size()),
..default()
},
..default()
},
GameEntityMarker,
));
player_data
.board
.get_next_pieces()
.iter()
.enumerate()
.for_each(|(index, _)| {
commands.spawn((
SpriteBundle {
transform: Transform::from_translation(
game_transform.next_piece_slot_background_translation(index),
),
sprite: Sprite {
color: RED.into(),
custom_size: Some(game_transform.next_piece_slot_background_size(index)),
..default()
},
visibility: player_data.next_piece_hint.get_visibility(index),
..default()
},
GameEntityMarker,
));
});

player_data
.board
.get_next_piece()
.get_squares_with_piece_center_align()
.get_next_pieces()
.iter()
.for_each(|sqr| {
.enumerate()
.for_each(|(index, _)| {
commands.spawn((
SpriteBundle {
transform: Transform::from_translation(
game_transform.next_piece_translation(sqr.0, sqr.1),
game_transform.next_piece_slot_translation(index),
),
sprite: Sprite {
custom_size: Some(game_transform.square_size()),
color: BLACK.into(),
custom_size: Some(game_transform.next_piece_slot_size(index)),
..default()
},
texture: square_image_assets
.get_image(SquareImageSize::Normal, player_data.board.get_next_piece()),
visibility: player_data.next_piece_hint.into(),
visibility: player_data.next_piece_hint.get_visibility(index),
..default()
},
GameEntityMarker,
NextPieceEntityMarker,
));
});

player_data
.board
.get_next_pieces()
.iter()
.enumerate()
.for_each(|(index, piece)| {
piece
.get_squares_with_piece_center_align()
.iter()
.for_each(|sqr| {
commands.spawn((
SpriteBundle {
transform: Transform::from_translation(
game_transform.next_piece_translation(sqr.0, sqr.1, index),
),
sprite: Sprite {
custom_size: Some(game_transform.next_piece_square_size(index)),
..default()
},
texture: square_image_assets.get_image(SquareImageSize::Normal, *piece),
visibility: player_data.next_piece_hint.get_visibility(index),
..default()
},
GameEntityMarker,
NextPieceEntityMarker(index),
));
});
});
}

fn increase_stopwatch_system(time: Res<Time>, mut player_data: ResMut<PlayerData>) {
Expand Down Expand Up @@ -806,7 +829,7 @@ mod state_game_entry_delay {
mut query: ParamSet<(
Query<(&mut Handle<Image>, &BoardSquareEntityMarker)>,
Query<(&mut Transform, &mut Handle<Image>), With<CurrPieceEntityMarker>>,
Query<(&mut Transform, &mut Handle<Image>), With<NextPieceEntityMarker>>,
Query<(&mut Transform, &mut Handle<Image>, &NextPieceEntityMarker)>,
Query<(&mut Handle<Image>, &PieceCountEntityMarker)>,
)>,
mut player_data: ResMut<PlayerData>,
Expand Down Expand Up @@ -841,13 +864,18 @@ mod state_game_entry_delay {
query.p2().iter_mut(),
player_data
.board
.get_next_piece()
.get_squares_with_piece_center_align(),
.get_next_pieces()
.iter()
.flat_map(|piece| piece.get_squares_with_piece_center_align())
.collect::<Vec<_>>(),
)
.for_each(|((mut transform, mut image), sqr)| {
*image = square_image_assets
.get_image(SquareImageSize::Normal, player_data.board.get_next_piece());
transform.translation = game_transform.next_piece_translation(sqr.0, sqr.1);
.for_each(|((mut transform, mut image, index), sqr)| {
*image = square_image_assets.get_image(
SquareImageSize::Normal,
player_data.board.get_next_pieces()[index.0],
);
transform.translation =
game_transform.next_piece_translation(sqr.0, sqr.1, index.0);
});
query.p3().iter_mut().for_each(|(mut image, piece)| {
*image = square_image_assets.get_image(SquareImageSize::Small, piece.0);
Expand Down
21 changes: 13 additions & 8 deletions src/game/rand.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use std::collections::VecDeque;

use num_traits::FromPrimitive;
use rand::Rng;

Expand Down Expand Up @@ -26,16 +28,19 @@ impl PieceRandomizer {
}
}

pub fn gen_1h2r(&self, piece: Piece) -> Piece {
pub fn gen_1h2r(&self, history: &VecDeque<Piece>) -> Piece {
match self {
PieceRandomizer::System => {
let index = rand::thread_rng().gen_range(0..Piece::variant_len());
if index + 1 != Piece::variant_len() && index != piece.variant_index() {
index.into()
} else {
self.gen()
PieceRandomizer::System => match history.back() {
Some(piece) => {
let index = rand::thread_rng().gen_range(0..Piece::variant_len());
if index + 1 != Piece::variant_len() && index != piece.variant_index() {
index.into()
} else {
self.gen()
}
}
}
None => self.gen(),
},
}
}
}
Loading

0 comments on commit 264237c

Please sign in to comment.