refactor patterns
This commit is contained in:
parent
099317ffc9
commit
33748e4956
44
src/board.rs
44
src/board.rs
@ -37,42 +37,35 @@ impl Board {
|
||||
y,
|
||||
}: &CurrentTetromino,
|
||||
) -> i8 {
|
||||
let pattern = tetromino.direction_pattern(direction);
|
||||
let pattern = tetromino.pattern(direction);
|
||||
let mut y = *y;
|
||||
loop {
|
||||
if self.pattern_and_position_colliding(pattern, *x, y) {
|
||||
if self.pattern_and_position_colliding(&pattern, *x, y) {
|
||||
break y - 1;
|
||||
}
|
||||
y += 1;
|
||||
}
|
||||
}
|
||||
|
||||
fn pattern_and_position_colliding(&self, pattern: [[bool; 4]; 4], x: i8, y: i8) -> bool {
|
||||
for (y_offset, row) in pattern.iter().enumerate() {
|
||||
for x_offset in row
|
||||
.iter()
|
||||
.enumerate()
|
||||
.filter(|(_, exists)| **exists)
|
||||
.map(|(x, _)| x)
|
||||
{
|
||||
let x = x_offset as i8 + x;
|
||||
let y = y_offset as i8 + y;
|
||||
fn pattern_and_position_colliding(&self, pattern: &Vec<(usize, usize)>, x: i8, y: i8) -> bool {
|
||||
for (x_offset, y_offset) in pattern {
|
||||
let x = *x_offset as i8 + x;
|
||||
let y = *y_offset as i8 + y;
|
||||
|
||||
if y < 0 {
|
||||
continue;
|
||||
}
|
||||
if y < 0 {
|
||||
continue;
|
||||
}
|
||||
|
||||
if y >= Board::HEIGHT as i8 {
|
||||
return true;
|
||||
}
|
||||
if y >= Board::HEIGHT as i8 {
|
||||
return true;
|
||||
}
|
||||
|
||||
if x < 0 || x >= Board::WIDTH as i8 {
|
||||
return true;
|
||||
}
|
||||
if x < 0 || x >= Board::WIDTH as i8 {
|
||||
return true;
|
||||
}
|
||||
|
||||
if self.0[y as usize][x as usize].is_some() {
|
||||
return true;
|
||||
}
|
||||
if self.0[y as usize][x as usize].is_some() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@ -88,8 +81,7 @@ impl Board {
|
||||
y,
|
||||
}: &CurrentTetromino,
|
||||
) -> bool {
|
||||
let pattern = tetromino.direction_pattern(direction);
|
||||
self.pattern_and_position_colliding(pattern, *x, *y)
|
||||
self.pattern_and_position_colliding(&tetromino.pattern(direction), *x, *y)
|
||||
}
|
||||
|
||||
pub fn lines_cleared(&mut self) -> usize {
|
||||
|
23
src/game.rs
23
src/game.rs
@ -250,27 +250,20 @@ impl Game {
|
||||
fn place_current_tetromino(&mut self) {
|
||||
let next = CurrentTetromino::new(self.take_next_in_bag(Tetromino::random()));
|
||||
let current = std::mem::replace(&mut self.current_tetromino, next);
|
||||
let pattern = current.tetromino.direction_pattern(¤t.direction);
|
||||
let pattern = current.tetromino.pattern(¤t.direction);
|
||||
|
||||
if current.y <= 0 {
|
||||
self.game_over = true;
|
||||
}
|
||||
|
||||
for (y, row) in pattern.iter().enumerate() {
|
||||
for x in row
|
||||
.iter()
|
||||
.enumerate()
|
||||
.filter(|(_, exists)| **exists)
|
||||
.map(|(x, _)| x)
|
||||
{
|
||||
let y = current.y + y as i8;
|
||||
if y < 0 {
|
||||
continue;
|
||||
}
|
||||
let y = y as usize;
|
||||
let x = (current.x + x as i8) as usize;
|
||||
self.board[y][x] = Some(current.tetromino.clone());
|
||||
for (x, y) in pattern {
|
||||
let y = current.y + y as i8;
|
||||
if y < 0 {
|
||||
continue;
|
||||
}
|
||||
let y = y as usize;
|
||||
let x = (current.x + x as i8) as usize;
|
||||
self.board[y][x] = Some(current.tetromino.clone());
|
||||
}
|
||||
|
||||
self.has_swapped_held = false;
|
||||
|
@ -194,6 +194,7 @@ pub fn start_game() -> Result<(), String> {
|
||||
}
|
||||
|
||||
ctx.draw_board(&game.board, &game.current_tetromino)?;
|
||||
ctx.draw_bag(&game.held_tetromino, &game.next_tetrominos)?;
|
||||
|
||||
if paused {
|
||||
ctx.draw_important_text(
|
||||
|
@ -1,4 +1,8 @@
|
||||
use crate::{board::Board, game::CurrentTetromino, tetromino::Tetromino};
|
||||
use crate::{
|
||||
board::Board,
|
||||
game::CurrentTetromino,
|
||||
tetromino::{Direction, Tetromino},
|
||||
};
|
||||
|
||||
pub trait UiCtx<Err> {
|
||||
fn window_size(&self) -> Result<(i32, i32), Err>;
|
||||
@ -34,25 +38,18 @@ pub trait GameUiCtx<Err>: UiCtx<Err> {
|
||||
x: i8,
|
||||
y: i8,
|
||||
color: Rgb,
|
||||
pattern: [[bool; 4]; 4],
|
||||
pattern: &Vec<(usize, usize)>,
|
||||
filled: bool,
|
||||
) -> Result<(), Err> {
|
||||
for (y_offset, row) in pattern.iter().enumerate() {
|
||||
for x_offset in row
|
||||
.iter()
|
||||
.enumerate()
|
||||
.filter(|(_, exists)| **exists)
|
||||
.map(|(x, _)| x)
|
||||
{
|
||||
let x = x_offset as i8 + x;
|
||||
let y = y_offset as i8 + y;
|
||||
for (x_offset, y_offset) in pattern {
|
||||
let x = *x_offset as i8 + x;
|
||||
let y = *y_offset as i8 + y;
|
||||
|
||||
if y < 0 {
|
||||
continue;
|
||||
}
|
||||
|
||||
self.draw_board_tile(x as i32, y as i32, &color, filled)?
|
||||
if y < 0 {
|
||||
continue;
|
||||
}
|
||||
|
||||
self.draw_board_tile(x as i32, y as i32, &color, filled)?
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
@ -63,13 +60,37 @@ pub trait GameUiCtx<Err>: UiCtx<Err> {
|
||||
let x = center(tile_size * Board::WIDTH as i32, win_width) + x * tile_size;
|
||||
let y = center(tile_size * Board::HEIGHT as i32, win_height) + y * tile_size;
|
||||
if filled {
|
||||
self.fill_rect(x, y, 24, 24, color)?;
|
||||
self.fill_rect(x, y, tile_size, tile_size, color)?;
|
||||
} else {
|
||||
self.outline_rect(x, y, 24, 24, color)?;
|
||||
self.outline_rect(x, y, tile_size, tile_size, color)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn draw_bag(&mut self, held: &Option<Tetromino>, next_up: &[Tetromino; 3]) -> Result<(), Err> {
|
||||
let (win_width, win_height) = self.window_size()?;
|
||||
let x = center(24 * Board::WIDTH as i32, win_width);
|
||||
let y = center(24 * Board::HEIGHT as i32, win_height);
|
||||
|
||||
let size = 24 * 5;
|
||||
let x = x - size - 16;
|
||||
|
||||
self.fill_rect(x, y, size, size, &Rgb(0, 0, 0))?;
|
||||
self.outline_rect(x - 1, y - 1, size + 2, size + 2, &Rgb(255, 255, 255))?;
|
||||
|
||||
if let Some(tetromino) = held {
|
||||
let color = Rgb::from_tetromino(&tetromino);
|
||||
let pattern = tetromino.pattern(&Direction::Up);
|
||||
for (x_offset, y_offset) in pattern {
|
||||
let x = x + (x_offset * 24) as i32;
|
||||
let y = y + (y_offset * 24) as i32;
|
||||
self.fill_rect(x, y, 24, 24, &color)?;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn draw_board(&mut self, board: &Board, current: &CurrentTetromino) -> Result<(), Err> {
|
||||
let (win_width, win_height) = self.window_size()?;
|
||||
self.outline_rect(
|
||||
@ -90,13 +111,13 @@ pub trait GameUiCtx<Err>: UiCtx<Err> {
|
||||
}
|
||||
}
|
||||
|
||||
let pattern = current.tetromino.direction_pattern(¤t.direction);
|
||||
let pattern = current.tetromino.pattern(¤t.direction);
|
||||
|
||||
self.draw_tetromino_from_parts(
|
||||
current.x,
|
||||
board.lowest_y(¤t),
|
||||
Rgb(255, 255, 255),
|
||||
pattern,
|
||||
&pattern,
|
||||
false,
|
||||
)?;
|
||||
|
||||
@ -104,7 +125,7 @@ pub trait GameUiCtx<Err>: UiCtx<Err> {
|
||||
current.x,
|
||||
current.y,
|
||||
Rgb::from_tetromino(¤t.tetromino),
|
||||
pattern,
|
||||
&pattern,
|
||||
true,
|
||||
)?;
|
||||
|
||||
@ -124,9 +145,23 @@ pub trait GameUiCtx<Err>: UiCtx<Err> {
|
||||
let x = center(width, win_width);
|
||||
let y = center(height, win_height);
|
||||
|
||||
self.outline_rect(x - 9, y - 9, width + 18, height + 18, &Rgb(255, 255, 255))?;
|
||||
let padding = 8;
|
||||
|
||||
self.fill_rect(x - 8, y - 8, width + 16, height + 16, &Rgb(16, 16, 16))?;
|
||||
self.outline_rect(
|
||||
x - padding - 1,
|
||||
y - padding - 1,
|
||||
width + padding * 2 + 2,
|
||||
height + padding * 2 + 2,
|
||||
&Rgb(255, 255, 255),
|
||||
)?;
|
||||
|
||||
self.fill_rect(
|
||||
x - padding,
|
||||
y - padding,
|
||||
width + padding * 2,
|
||||
height + padding * 2,
|
||||
&Rgb(16, 16, 16),
|
||||
)?;
|
||||
self.fill_text(font, text, x, y, width, height)?;
|
||||
|
||||
Ok(())
|
||||
|
@ -51,7 +51,19 @@ impl Tetromino {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn direction_pattern(&self, direction: &Direction) -> [[bool; 4]; 4] {
|
||||
pub fn pattern(&self, direction: &Direction) -> Vec<(usize, usize)> {
|
||||
self.raw_pattern(direction)
|
||||
.into_iter()
|
||||
.enumerate()
|
||||
.flat_map(|(y, row)| {
|
||||
row.into_iter()
|
||||
.enumerate()
|
||||
.filter_map(move |(x, available)| if available { Some((x, y)) } else { None })
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn raw_pattern(&self, direction: &Direction) -> [[bool; 4]; 4] {
|
||||
let dir = match self {
|
||||
Self::I => match direction {
|
||||
Direction::Up => [
|
||||
|
Loading…
Reference in New Issue
Block a user