draw ghost
This commit is contained in:
parent
fc6ebcdbc2
commit
7d6822cd34
38
src/board.rs
38
src/board.rs
@ -28,26 +28,35 @@ impl Board {
|
||||
Board(board)
|
||||
}
|
||||
|
||||
pub fn colliding(
|
||||
pub fn lowest_y(
|
||||
&self,
|
||||
CurrentTetromino {
|
||||
tetromino,
|
||||
direction,
|
||||
x: cur_x,
|
||||
y: cur_y,
|
||||
x,
|
||||
y,
|
||||
}: &CurrentTetromino,
|
||||
) -> bool {
|
||||
) -> i8 {
|
||||
let pattern = tetromino.direction_pattern(direction);
|
||||
let mut y = *y;
|
||||
loop {
|
||||
if self.pattern_and_position_colliding(pattern, *x, y) {
|
||||
break y - 1;
|
||||
}
|
||||
y += 1;
|
||||
}
|
||||
}
|
||||
|
||||
for (y, row) in pattern.iter().enumerate() {
|
||||
for x in row
|
||||
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 as i8 + cur_x;
|
||||
let y = y as i8 + cur_y;
|
||||
let x = x_offset as i8 + x;
|
||||
let y = y_offset as i8 + y;
|
||||
|
||||
if y < 0 {
|
||||
continue;
|
||||
@ -70,6 +79,19 @@ impl Board {
|
||||
false
|
||||
}
|
||||
|
||||
pub fn colliding(
|
||||
&self,
|
||||
CurrentTetromino {
|
||||
tetromino,
|
||||
direction,
|
||||
x,
|
||||
y,
|
||||
}: &CurrentTetromino,
|
||||
) -> bool {
|
||||
let pattern = tetromino.direction_pattern(direction);
|
||||
self.pattern_and_position_colliding(pattern, *x, *y)
|
||||
}
|
||||
|
||||
pub fn lines_cleared(&mut self) -> usize {
|
||||
let line_clears: Vec<_> = self
|
||||
.iter()
|
||||
|
160
src/sdl_impl.rs
160
src/sdl_impl.rs
@ -1,42 +1,85 @@
|
||||
use crate::actions::{Action, ActionsHeld};
|
||||
use crate::board::Board;
|
||||
use crate::game::{CurrentTetromino, Game};
|
||||
use crate::tetromino::Tetromino;
|
||||
use crate::Rgb;
|
||||
use sdl2::event::Event;
|
||||
use sdl2::keyboard::Keycode;
|
||||
use sdl2::pixels::Color;
|
||||
use sdl2::rect::Rect;
|
||||
use sdl2::render::{Canvas, RenderTarget, Texture, TextureCreator, WindowCanvas};
|
||||
use sdl2::render::{Texture, TextureCreator, WindowCanvas};
|
||||
use sdl2::rwops::RWops;
|
||||
use sdl2::ttf::Sdl2TtfContext;
|
||||
use std::time::Duration;
|
||||
|
||||
fn draw_board_tile(canvas: &mut WindowCanvas, width: usize, height: usize, color: Rgb) {
|
||||
const WIDTH: i32 = 1000;
|
||||
const HEIGHT: i32 = 800;
|
||||
|
||||
fn draw_board_tile(
|
||||
canvas: &mut WindowCanvas,
|
||||
width: usize,
|
||||
height: usize,
|
||||
color: &Rgb,
|
||||
filled: bool,
|
||||
) -> Result<(), String> {
|
||||
canvas.set_draw_color(Color::RGB(color.0, color.1, color.2));
|
||||
canvas
|
||||
.fill_rect(Rect::new(
|
||||
center(24 * Board::WIDTH as i32, 800) + width as i32 * 24,
|
||||
center(24 * Board::HEIGHT as i32, 600) + height as i32 * 24,
|
||||
24,
|
||||
24,
|
||||
))
|
||||
.unwrap();
|
||||
let rect = Rect::new(
|
||||
center(24 * Board::WIDTH as i32, WIDTH) + width as i32 * 24,
|
||||
center(24 * Board::HEIGHT as i32, HEIGHT) + height as i32 * 24,
|
||||
24,
|
||||
24,
|
||||
);
|
||||
if filled {
|
||||
canvas.fill_rect(rect)
|
||||
} else {
|
||||
canvas.draw_rect(rect)
|
||||
}
|
||||
}
|
||||
|
||||
fn center(length: i32, max: i32) -> i32 {
|
||||
(max - length) / 2
|
||||
}
|
||||
|
||||
fn draw_board(canvas: &mut WindowCanvas, board: &Board, current: &CurrentTetromino) {
|
||||
fn draw_tetromino_from_parts(
|
||||
canvas: &mut WindowCanvas,
|
||||
x: i8,
|
||||
y: i8,
|
||||
color: Rgb,
|
||||
pattern: [[bool; 4]; 4],
|
||||
filled: bool,
|
||||
) -> Result<(), String> {
|
||||
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;
|
||||
|
||||
if y < 0 {
|
||||
continue;
|
||||
}
|
||||
|
||||
draw_board_tile(canvas, x as usize, y as usize, &color, filled)?
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn draw_board(
|
||||
canvas: &mut WindowCanvas,
|
||||
board: &Board,
|
||||
current: &CurrentTetromino,
|
||||
) -> Result<(), String> {
|
||||
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();
|
||||
canvas.draw_rect(Rect::new(
|
||||
center(24 * Board::WIDTH as i32, WIDTH) - 1,
|
||||
center(24 * Board::HEIGHT as i32, HEIGHT) - 1,
|
||||
24 * Board::WIDTH as u32 + 2,
|
||||
24 * Board::HEIGHT as u32 + 2,
|
||||
))?;
|
||||
|
||||
for (y, row) in board.iter().enumerate() {
|
||||
for (x, piece) in row.iter().enumerate() {
|
||||
@ -44,53 +87,48 @@ fn draw_board(canvas: &mut WindowCanvas, board: &Board, current: &CurrentTetromi
|
||||
Some(t) => Rgb::from_tetromino(t),
|
||||
None => Rgb(0, 0, 0),
|
||||
};
|
||||
draw_board_tile(canvas, x, y, color)
|
||||
draw_board_tile(canvas, x, y, &color, true)?
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
draw_tetromino_from_parts(
|
||||
canvas,
|
||||
current.x,
|
||||
board.lowest_y(¤t),
|
||||
Rgb(255, 255, 255),
|
||||
pattern,
|
||||
false,
|
||||
)?;
|
||||
|
||||
if y < 0 {
|
||||
continue;
|
||||
}
|
||||
draw_tetromino_from_parts(
|
||||
canvas,
|
||||
current.x,
|
||||
current.y,
|
||||
Rgb::from_tetromino(¤t.tetromino),
|
||||
pattern,
|
||||
true,
|
||||
)?;
|
||||
|
||||
draw_board_tile(
|
||||
canvas,
|
||||
x as usize,
|
||||
y as usize,
|
||||
Rgb::from_tetromino(¤t.tetromino),
|
||||
)
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
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();
|
||||
) -> Result<Texture<'font>, String> {
|
||||
let font = ttf_context.load_font_from_rwops(
|
||||
RWops::from_bytes(include_bytes!("res/josenfin_sans_regular.ttf"))?,
|
||||
24,
|
||||
)?;
|
||||
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
|
||||
Ok(texture)
|
||||
}
|
||||
|
||||
fn draw_important_text(
|
||||
@ -99,14 +137,14 @@ fn draw_important_text(
|
||||
ttf_context: &Sdl2TtfContext,
|
||||
) -> Result<(), String> {
|
||||
let texture_creator = canvas.texture_creator();
|
||||
let texture = font_texture(text, &ttf_context, &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);
|
||||
let x = center(width as i32, WIDTH);
|
||||
let y = center(height as i32, HEIGHT);
|
||||
|
||||
canvas.set_draw_color(Color::WHITE);
|
||||
canvas.draw_rect(Rect::new(x - 9, y - 9, width + 18, height + 18))?;
|
||||
@ -118,23 +156,23 @@ fn draw_important_text(
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn start_game() {
|
||||
pub fn start_game() -> Result<(), String> {
|
||||
let mut game = Game::new();
|
||||
let mut actions = ActionsHeld::new();
|
||||
let mut paused = false;
|
||||
|
||||
let sdl_context = sdl2::init().unwrap();
|
||||
let sdl_context = sdl2::init()?;
|
||||
let ttf_context = sdl2::ttf::init().unwrap();
|
||||
let video_subsystem = sdl_context.video().unwrap();
|
||||
let video_subsystem = sdl_context.video()?;
|
||||
|
||||
let window = video_subsystem
|
||||
.window("reimtris2", 800, 600)
|
||||
.window("reimtris2", WIDTH as u32, HEIGHT as u32)
|
||||
.position_centered()
|
||||
.build()
|
||||
.unwrap();
|
||||
|
||||
let mut canvas = window.into_canvas().build().unwrap();
|
||||
let mut event_pump = sdl_context.event_pump().unwrap();
|
||||
let mut event_pump = sdl_context.event_pump()?;
|
||||
'running: loop {
|
||||
canvas.set_draw_color(Color::RGB(16, 16, 16));
|
||||
canvas.clear();
|
||||
@ -144,7 +182,7 @@ pub fn start_game() {
|
||||
| Event::KeyDown {
|
||||
keycode: Some(Keycode::Escape),
|
||||
..
|
||||
} => break 'running,
|
||||
} => break 'running Ok(()),
|
||||
Event::KeyDown {
|
||||
keycode: Some(keycode),
|
||||
..
|
||||
@ -189,22 +227,20 @@ pub fn start_game() {
|
||||
}
|
||||
}
|
||||
|
||||
draw_board(&mut canvas, &game.board, &game.current_tetromino);
|
||||
draw_board(&mut canvas, &game.board, &game.current_tetromino)?;
|
||||
|
||||
if paused {
|
||||
draw_important_text(
|
||||
"game paused o_o... press [p] to unpause !!",
|
||||
&mut canvas,
|
||||
&ttf_context,
|
||||
)
|
||||
.unwrap();
|
||||
)?;
|
||||
} else if game.game_over {
|
||||
draw_important_text(
|
||||
"game over T_T... press [enter] 2 restart :D",
|
||||
&mut canvas,
|
||||
&ttf_context,
|
||||
)
|
||||
.unwrap();
|
||||
)?;
|
||||
} else {
|
||||
game.step(&actions);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user