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