pause/game over
This commit is contained in:
parent
63a8c0bd78
commit
fc6ebcdbc2
@ -5,4 +5,7 @@ edition = "2021"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
rand = "0.9.0"
|
rand = "0.9.0"
|
||||||
sdl2 = "0.37.0"
|
|
||||||
|
[dependencies.sdl2]
|
||||||
|
version = "0.37.0"
|
||||||
|
features = ["ttf"]
|
||||||
|
77
src/game.rs
77
src/game.rs
@ -22,6 +22,7 @@ impl CurrentTetromino {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct Game {
|
pub struct Game {
|
||||||
|
pub game_over: bool,
|
||||||
pub board: Board,
|
pub board: Board,
|
||||||
pub next_tetrominos: [Tetromino; 3],
|
pub next_tetrominos: [Tetromino; 3],
|
||||||
pub current_tetromino: CurrentTetromino,
|
pub current_tetromino: CurrentTetromino,
|
||||||
@ -31,11 +32,18 @@ pub struct Game {
|
|||||||
pub ticks: usize,
|
pub ticks: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Score {
|
pub enum SoundEffect {
|
||||||
level: usize,
|
HardDrop,
|
||||||
points: usize,
|
LineClear(usize),
|
||||||
lines: usize,
|
Move,
|
||||||
combo: usize,
|
Rotation,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Score {
|
||||||
|
pub level: usize,
|
||||||
|
pub points: usize,
|
||||||
|
pub lines: usize,
|
||||||
|
pub combo: usize,
|
||||||
back_to_back: bool,
|
back_to_back: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -81,6 +89,7 @@ impl Score {
|
|||||||
impl Game {
|
impl Game {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
game_over: false,
|
||||||
board: Board::new(),
|
board: Board::new(),
|
||||||
next_tetrominos: std::array::from_fn(|_| Tetromino::random()),
|
next_tetrominos: std::array::from_fn(|_| Tetromino::random()),
|
||||||
current_tetromino: CurrentTetromino::new(Tetromino::random()),
|
current_tetromino: CurrentTetromino::new(Tetromino::random()),
|
||||||
@ -97,7 +106,7 @@ impl Game {
|
|||||||
last
|
last
|
||||||
}
|
}
|
||||||
|
|
||||||
fn hard_drop(&mut self, actions: &ActionsHeld) {
|
fn try_hard_drop(&mut self, actions: &ActionsHeld, effects: &mut Vec<SoundEffect>) {
|
||||||
if !actions.just_pressed(self.ticks, &Action::HardDrop) {
|
if !actions.just_pressed(self.ticks, &Action::HardDrop) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -110,12 +119,12 @@ impl Game {
|
|||||||
self.current_tetromino.y -= 1;
|
self.current_tetromino.y -= 1;
|
||||||
self.score.points += (self.current_tetromino.y - start_y) as usize * 2;
|
self.score.points += (self.current_tetromino.y - start_y) as usize * 2;
|
||||||
self.place_current_tetromino();
|
self.place_current_tetromino();
|
||||||
self.check_line_clears();
|
self.check_line_clears(effects);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn soft_drop(&mut self, actions: &ActionsHeld) {
|
fn soft_drop(&mut self, actions: &ActionsHeld, effects: &mut Vec<SoundEffect>) {
|
||||||
let mut delay = 32 - self.score.level * 2;
|
let mut delay = 32 - self.score.level * 2;
|
||||||
if actions.contains_key(&Action::SoftDrop) {
|
if actions.contains_key(&Action::SoftDrop) {
|
||||||
delay /= 10;
|
delay /= 10;
|
||||||
@ -129,13 +138,13 @@ impl Game {
|
|||||||
if self.board.colliding(&self.current_tetromino) {
|
if self.board.colliding(&self.current_tetromino) {
|
||||||
self.current_tetromino.y -= 1;
|
self.current_tetromino.y -= 1;
|
||||||
self.place_current_tetromino();
|
self.place_current_tetromino();
|
||||||
self.check_line_clears();
|
self.check_line_clears(effects);
|
||||||
} else if actions.contains_key(&Action::SoftDrop) {
|
} else if actions.contains_key(&Action::SoftDrop) {
|
||||||
self.score.points += 1;
|
self.score.points += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn move_horizontally(&mut self, actions: &ActionsHeld) {
|
fn try_move_horizontally(&mut self, actions: &ActionsHeld, effects: &mut Vec<SoundEffect>) {
|
||||||
for key in [Action::Left, Action::Right] {
|
for key in [Action::Left, Action::Right] {
|
||||||
let just_pressed = actions.just_pressed(self.ticks, &key);
|
let just_pressed = actions.just_pressed(self.ticks, &key);
|
||||||
let long_press = actions.held_for(self.ticks, &key, |held_for| held_for > 15);
|
let long_press = actions.held_for(self.ticks, &key, |held_for| held_for > 15);
|
||||||
@ -150,11 +159,13 @@ impl Game {
|
|||||||
self.current_tetromino.x += offset;
|
self.current_tetromino.x += offset;
|
||||||
if self.board.colliding(&self.current_tetromino) {
|
if self.board.colliding(&self.current_tetromino) {
|
||||||
self.current_tetromino.x -= offset;
|
self.current_tetromino.x -= offset;
|
||||||
|
} else {
|
||||||
|
effects.push(SoundEffect::Move);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_line_clears(&mut self) {
|
fn check_line_clears(&mut self, effects: &mut Vec<SoundEffect>) {
|
||||||
let lines_cleared = self.board.lines_cleared();
|
let lines_cleared = self.board.lines_cleared();
|
||||||
|
|
||||||
self.score.level_up(lines_cleared);
|
self.score.level_up(lines_cleared);
|
||||||
@ -177,20 +188,24 @@ impl Game {
|
|||||||
|
|
||||||
if lines_cleared > 0 {
|
if lines_cleared > 0 {
|
||||||
self.score.combo += 1;
|
self.score.combo += 1;
|
||||||
// play_line_clears_sound();
|
effects.push(SoundEffect::LineClear(lines_cleared));
|
||||||
} else {
|
} else {
|
||||||
self.score.combo = 0;
|
self.score.combo = 0;
|
||||||
// play_hard_drop_sound();
|
effects.push(SoundEffect::HardDrop);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn step(&mut self, actions: &ActionsHeld) {
|
pub fn step(&mut self, actions: &ActionsHeld) -> Vec<SoundEffect> {
|
||||||
self.hard_drop(actions);
|
if self.game_over {
|
||||||
self.soft_drop(actions);
|
panic!("should check if game is over before stepping");
|
||||||
self.move_horizontally(actions);
|
}
|
||||||
|
let mut effects = Vec::new();
|
||||||
|
self.try_hard_drop(actions, &mut effects);
|
||||||
|
self.soft_drop(actions, &mut effects);
|
||||||
|
self.try_move_horizontally(actions, &mut effects);
|
||||||
|
|
||||||
if actions.just_pressed(self.ticks, &Action::Swap) {
|
if actions.just_pressed(self.ticks, &Action::Swap) {
|
||||||
self.try_swap_tetromino();
|
self.try_swap_tetromino(&mut effects);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (control, direction) in [
|
for (control, direction) in [
|
||||||
@ -200,16 +215,18 @@ impl Game {
|
|||||||
if !actions.just_pressed(self.ticks, &control) {
|
if !actions.just_pressed(self.ticks, &control) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
self.try_rotate(direction);
|
self.try_rotate(direction, &mut effects);
|
||||||
}
|
}
|
||||||
self.ticks += 1;
|
self.ticks += 1;
|
||||||
|
effects
|
||||||
}
|
}
|
||||||
|
|
||||||
fn try_rotate(&mut self, diff: DirectionDiff) -> bool {
|
fn try_rotate(&mut self, diff: DirectionDiff, effects: &mut Vec<SoundEffect>) {
|
||||||
let rotated = self.current_tetromino.direction.rotate(&diff);
|
let rotated = self.current_tetromino.direction.rotate(&diff);
|
||||||
let old_direction = std::mem::replace(&mut self.current_tetromino.direction, rotated);
|
let old_direction = std::mem::replace(&mut self.current_tetromino.direction, rotated);
|
||||||
if !self.board.colliding(&self.current_tetromino) {
|
if !self.board.colliding(&self.current_tetromino) {
|
||||||
return true;
|
effects.push(SoundEffect::Rotation);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
let wall_kicks = self
|
let wall_kicks = self
|
||||||
.current_tetromino
|
.current_tetromino
|
||||||
@ -220,14 +237,14 @@ impl Game {
|
|||||||
self.current_tetromino.x += x;
|
self.current_tetromino.x += x;
|
||||||
self.current_tetromino.y += y;
|
self.current_tetromino.y += y;
|
||||||
if !(self.board.colliding(&self.current_tetromino)) {
|
if !(self.board.colliding(&self.current_tetromino)) {
|
||||||
return true;
|
effects.push(SoundEffect::Rotation);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
self.current_tetromino.x -= x;
|
self.current_tetromino.x -= x;
|
||||||
self.current_tetromino.y -= y;
|
self.current_tetromino.y -= y;
|
||||||
}
|
}
|
||||||
|
|
||||||
self.current_tetromino.direction = old_direction;
|
self.current_tetromino.direction = old_direction;
|
||||||
false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn place_current_tetromino(&mut self) {
|
fn place_current_tetromino(&mut self) {
|
||||||
@ -235,6 +252,10 @@ impl Game {
|
|||||||
let current = std::mem::replace(&mut self.current_tetromino, next);
|
let current = std::mem::replace(&mut self.current_tetromino, next);
|
||||||
let pattern = current.tetromino.direction_pattern(¤t.direction);
|
let pattern = current.tetromino.direction_pattern(¤t.direction);
|
||||||
|
|
||||||
|
if current.y <= 0 {
|
||||||
|
self.game_over = true;
|
||||||
|
}
|
||||||
|
|
||||||
for (y, row) in pattern.iter().enumerate() {
|
for (y, row) in pattern.iter().enumerate() {
|
||||||
for x in row
|
for x in row
|
||||||
.iter()
|
.iter()
|
||||||
@ -242,7 +263,11 @@ impl Game {
|
|||||||
.filter(|(_, exists)| **exists)
|
.filter(|(_, exists)| **exists)
|
||||||
.map(|(x, _)| x)
|
.map(|(x, _)| x)
|
||||||
{
|
{
|
||||||
let y = (current.y + y as i8) as usize;
|
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;
|
let x = (current.x + x as i8) as usize;
|
||||||
self.board[y][x] = Some(current.tetromino.clone());
|
self.board[y][x] = Some(current.tetromino.clone());
|
||||||
}
|
}
|
||||||
@ -251,7 +276,7 @@ impl Game {
|
|||||||
self.has_swapped_held = false;
|
self.has_swapped_held = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn try_swap_tetromino(&mut self) {
|
fn try_swap_tetromino(&mut self, effects: &mut Vec<SoundEffect>) {
|
||||||
if self.has_swapped_held {
|
if self.has_swapped_held {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -263,6 +288,7 @@ impl Game {
|
|||||||
let current_tetromino = CurrentTetromino::new(held_or_first_in_bag_tetromino);
|
let current_tetromino = CurrentTetromino::new(held_or_first_in_bag_tetromino);
|
||||||
let old_tetromino = std::mem::replace(&mut self.current_tetromino, current_tetromino);
|
let old_tetromino = std::mem::replace(&mut self.current_tetromino, current_tetromino);
|
||||||
self.held_tetromino.replace(old_tetromino.tetromino);
|
self.held_tetromino.replace(old_tetromino.tetromino);
|
||||||
|
effects.push(SoundEffect::Rotation);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -273,6 +299,7 @@ mod test {
|
|||||||
#[test]
|
#[test]
|
||||||
fn advance_bag() {
|
fn advance_bag() {
|
||||||
let mut game = Game {
|
let mut game = Game {
|
||||||
|
game_over: false,
|
||||||
board: Board::new(),
|
board: Board::new(),
|
||||||
score: Score::new(),
|
score: Score::new(),
|
||||||
next_tetrominos: [Tetromino::I, Tetromino::J, Tetromino::O],
|
next_tetrominos: [Tetromino::I, Tetromino::J, Tetromino::O],
|
||||||
|
189
src/sdl_impl.rs
189
src/sdl_impl.rs
@ -1,31 +1,130 @@
|
|||||||
use crate::actions::{Action, ActionsHeld};
|
use crate::actions::{Action, ActionsHeld};
|
||||||
use crate::board::Board;
|
use crate::board::Board;
|
||||||
use crate::game::Game;
|
use crate::game::{CurrentTetromino, Game};
|
||||||
use crate::Rgb;
|
use crate::Rgb;
|
||||||
use sdl2::event::Event;
|
use sdl2::event::Event;
|
||||||
use sdl2::keyboard::Keycode;
|
use sdl2::keyboard::Keycode;
|
||||||
use sdl2::pixels::Color;
|
use sdl2::pixels::Color;
|
||||||
use sdl2::rect::Rect;
|
use sdl2::rect::Rect;
|
||||||
use sdl2::render::WindowCanvas;
|
use sdl2::render::{Canvas, RenderTarget, Texture, TextureCreator, WindowCanvas};
|
||||||
|
use sdl2::rwops::RWops;
|
||||||
|
use sdl2::ttf::Sdl2TtfContext;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
fn draw_board(canvas: &mut WindowCanvas, width: usize, height: usize, color: Rgb) {
|
fn draw_board_tile(canvas: &mut WindowCanvas, width: usize, height: usize, color: Rgb) {
|
||||||
canvas.set_draw_color(Color::RGB(color.0, color.1, color.2));
|
canvas.set_draw_color(Color::RGB(color.0, color.1, color.2));
|
||||||
canvas
|
canvas
|
||||||
.fill_rect(Rect::new(
|
.fill_rect(Rect::new(
|
||||||
(800 - 24 * Board::WIDTH as i32) / 2 + width as i32 * 24,
|
center(24 * Board::WIDTH as i32, 800) + width as i32 * 24,
|
||||||
(600 - 24 * Board::HEIGHT as i32) / 2 + height as i32 * 24,
|
center(24 * Board::HEIGHT as i32, 600) + height as i32 * 24,
|
||||||
24,
|
24,
|
||||||
24,
|
24,
|
||||||
))
|
))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn center(length: i32, max: i32) -> i32 {
|
||||||
|
(max - length) / 2
|
||||||
|
}
|
||||||
|
|
||||||
|
fn draw_board(canvas: &mut WindowCanvas, board: &Board, current: &CurrentTetromino) {
|
||||||
|
canvas.set_draw_color(Color::WHITE);
|
||||||
|
canvas
|
||||||
|
.draw_rect(Rect::new(
|
||||||
|
center(24 * Board::WIDTH as i32, 800) - 1,
|
||||||
|
center(24 * Board::HEIGHT as i32, 600) - 1,
|
||||||
|
24 * Board::WIDTH as u32 + 2,
|
||||||
|
24 * Board::HEIGHT as u32 + 2,
|
||||||
|
))
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
for (y, row) in board.iter().enumerate() {
|
||||||
|
for (x, piece) in row.iter().enumerate() {
|
||||||
|
let color = match piece {
|
||||||
|
Some(t) => Rgb::from_tetromino(t),
|
||||||
|
None => Rgb(0, 0, 0),
|
||||||
|
};
|
||||||
|
draw_board_tile(canvas, x, y, color)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let pattern = current.tetromino.direction_pattern(¤t.direction);
|
||||||
|
|
||||||
|
for (y, row) in pattern.iter().enumerate() {
|
||||||
|
for x in row
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.filter(|(_, exists)| **exists)
|
||||||
|
.map(|(x, _)| x)
|
||||||
|
{
|
||||||
|
let x = x as i8 + current.x;
|
||||||
|
let y = y as i8 + current.y;
|
||||||
|
|
||||||
|
if y < 0 {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
draw_board_tile(
|
||||||
|
canvas,
|
||||||
|
x as usize,
|
||||||
|
y as usize,
|
||||||
|
Rgb::from_tetromino(¤t.tetromino),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn font_texture<'font, 'a, C>(
|
||||||
|
text: &'a str,
|
||||||
|
ttf_context: &'a Sdl2TtfContext,
|
||||||
|
texture_creator: &'font TextureCreator<C>,
|
||||||
|
) -> Texture<'font> {
|
||||||
|
let font = ttf_context
|
||||||
|
.load_font_from_rwops(
|
||||||
|
RWops::from_bytes(include_bytes!("res/josenfin_sans_regular.ttf")).unwrap(),
|
||||||
|
24,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
let game_over_text = font.render(text).solid(Color::RGB(255, 255, 255)).unwrap();
|
||||||
|
let texture = texture_creator
|
||||||
|
.create_texture_from_surface(game_over_text)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
texture
|
||||||
|
}
|
||||||
|
|
||||||
|
fn draw_important_text(
|
||||||
|
text: &str,
|
||||||
|
canvas: &mut WindowCanvas,
|
||||||
|
ttf_context: &Sdl2TtfContext,
|
||||||
|
) -> Result<(), String> {
|
||||||
|
let texture_creator = canvas.texture_creator();
|
||||||
|
let texture = font_texture(text, &ttf_context, &texture_creator);
|
||||||
|
|
||||||
|
let size = texture.query();
|
||||||
|
let width = size.width;
|
||||||
|
let height = size.height;
|
||||||
|
|
||||||
|
let x = center(width as i32, 800);
|
||||||
|
let y = center(height as i32, 600);
|
||||||
|
|
||||||
|
canvas.set_draw_color(Color::WHITE);
|
||||||
|
canvas.draw_rect(Rect::new(x - 9, y - 9, width + 18, height + 18))?;
|
||||||
|
|
||||||
|
canvas.set_draw_color(Color::RGB(16, 16, 16));
|
||||||
|
canvas.fill_rect(Rect::new(x - 8, y - 8, width + 16, height + 16))?;
|
||||||
|
canvas.copy(&texture, None, Some(Rect::new(x, y, width, height)))?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn start_game() {
|
pub fn start_game() {
|
||||||
let mut game = Game::new();
|
let mut game = Game::new();
|
||||||
let mut actions = ActionsHeld::new();
|
let mut actions = ActionsHeld::new();
|
||||||
|
let mut paused = false;
|
||||||
|
|
||||||
let sdl_context = sdl2::init().unwrap();
|
let sdl_context = sdl2::init().unwrap();
|
||||||
|
let ttf_context = sdl2::ttf::init().unwrap();
|
||||||
let video_subsystem = sdl_context.video().unwrap();
|
let video_subsystem = sdl_context.video().unwrap();
|
||||||
|
|
||||||
let window = video_subsystem
|
let window = video_subsystem
|
||||||
@ -51,6 +150,14 @@ pub fn start_game() {
|
|||||||
..
|
..
|
||||||
} => {
|
} => {
|
||||||
let keycode = match keycode {
|
let keycode = match keycode {
|
||||||
|
Keycode::Return if !paused && game.game_over => {
|
||||||
|
game = Game::new();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
Keycode::P => {
|
||||||
|
paused = !paused;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
Keycode::Left | Keycode::A => Action::Left,
|
Keycode::Left | Keycode::A => Action::Left,
|
||||||
Keycode::Right | Keycode::D => Action::Right,
|
Keycode::Right | Keycode::D => Action::Right,
|
||||||
Keycode::Down | Keycode::S => Action::SoftDrop,
|
Keycode::Down | Keycode::S => Action::SoftDrop,
|
||||||
@ -82,64 +189,26 @@ pub fn start_game() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
canvas.set_draw_color(Color::WHITE);
|
draw_board(&mut canvas, &game.board, &game.current_tetromino);
|
||||||
canvas
|
|
||||||
.draw_rect(Rect::new(
|
if paused {
|
||||||
(800 - 24 * Board::WIDTH as i32) / 2 - 1,
|
draw_important_text(
|
||||||
(600 - 24 * Board::HEIGHT as i32) / 2 - 1,
|
"game paused o_o... press [p] to unpause !!",
|
||||||
24 * Board::WIDTH as u32 + 2,
|
&mut canvas,
|
||||||
24 * Board::HEIGHT as u32 + 2,
|
&ttf_context,
|
||||||
))
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
} else if game.game_over {
|
||||||
for (y, row) in game.board.iter().enumerate() {
|
draw_important_text(
|
||||||
for (x, piece) in row.iter().enumerate() {
|
"game over T_T... press [enter] 2 restart :D",
|
||||||
let color = match piece {
|
&mut canvas,
|
||||||
Some(t) => Rgb::from_tetromino(t),
|
&ttf_context,
|
||||||
None => Rgb(0, 0, 0),
|
)
|
||||||
};
|
.unwrap();
|
||||||
draw_board(&mut canvas, x, y, color)
|
} else {
|
||||||
}
|
game.step(&actions);
|
||||||
}
|
}
|
||||||
|
|
||||||
let pattern = game
|
|
||||||
.current_tetromino
|
|
||||||
.tetromino
|
|
||||||
.direction_pattern(&game.current_tetromino.direction);
|
|
||||||
|
|
||||||
for (y, row) in pattern.iter().enumerate() {
|
|
||||||
for x in row
|
|
||||||
.iter()
|
|
||||||
.enumerate()
|
|
||||||
.filter(|(_, exists)| **exists)
|
|
||||||
.map(|(x, _)| x)
|
|
||||||
{
|
|
||||||
let x = x as i8 + game.current_tetromino.x;
|
|
||||||
let y = y as i8 + game.current_tetromino.y;
|
|
||||||
|
|
||||||
if y < 0 {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if y >= Board::HEIGHT as i8 {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if x < 0 || x >= Board::WIDTH as i8 {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
draw_board(
|
|
||||||
&mut canvas,
|
|
||||||
x as usize,
|
|
||||||
y as usize,
|
|
||||||
Rgb::from_tetromino(&game.current_tetromino.tetromino),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
game.step(&actions);
|
|
||||||
|
|
||||||
canvas.present();
|
canvas.present();
|
||||||
::std::thread::sleep(Duration::new(0, 1_000_000_000u32 / 60));
|
::std::thread::sleep(Duration::new(0, 1_000_000_000u32 / 60));
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user