136 lines
4.2 KiB
Rust
136 lines
4.2 KiB
Rust
use crate::{
|
|
game::Game,
|
|
graphics::{MinoColor, Renderable, BORDER_RADIUS, CELL_SIZE, COLOR_BACKGROUND, UI_PADDING},
|
|
playfield::{PlayField, PLAYFIELD_HEIGHT, PLAYFIELD_WIDTH},
|
|
tetromino::{Position, RotationState, Tetromino, TetrominoType},
|
|
};
|
|
use sdl2::{
|
|
pixels::Color,
|
|
rect::Rect,
|
|
render::{Canvas, RenderTarget},
|
|
video::Window,
|
|
};
|
|
|
|
pub fn render(canvas: &mut Canvas<Window>, game: &Game) {
|
|
let (x, y) = canvas.window().size();
|
|
let game_width = game.width() as i32;
|
|
let game_height = game.height() as i32;
|
|
canvas.set_viewport(Some(Rect::new(
|
|
x as i32 / 2 - game_width / 2 as i32,
|
|
y as i32 / 2 - game_height / 2 as i32,
|
|
game_width as u32,
|
|
game_height as u32,
|
|
)));
|
|
game.render(canvas);
|
|
}
|
|
|
|
impl Renderable for Game {
|
|
fn width(&self) -> usize {
|
|
self.playfield().width()
|
|
}
|
|
|
|
fn height(&self) -> usize {
|
|
self.playfield().height()
|
|
}
|
|
|
|
fn render<R: RenderTarget>(&self, canvas: &mut Canvas<R>) -> Result<(), String> {
|
|
self.playfield().render(canvas)
|
|
}
|
|
}
|
|
|
|
impl Renderable for PlayField {
|
|
fn width(&self) -> usize {
|
|
(CELL_SIZE as usize) * PLAYFIELD_WIDTH
|
|
}
|
|
|
|
fn height(&self) -> usize {
|
|
(CELL_SIZE as usize) * PLAYFIELD_HEIGHT
|
|
}
|
|
|
|
fn render<R: RenderTarget>(&self, canvas: &mut Canvas<R>) -> Result<(), String> {
|
|
for y in 0..PLAYFIELD_HEIGHT {
|
|
for x in 0..PLAYFIELD_WIDTH {
|
|
canvas.set_draw_color(Color::RGB(0, 0, 0));
|
|
canvas.fill_rect(Rect::new(
|
|
CELL_SIZE as i32 * x as i32,
|
|
CELL_SIZE as i32 * y as i32,
|
|
CELL_SIZE,
|
|
CELL_SIZE,
|
|
))?;
|
|
|
|
match self.field()[y + PLAYFIELD_HEIGHT][x] {
|
|
Some(mino) => canvas.set_draw_color(mino),
|
|
None => canvas.set_draw_color(COLOR_BACKGROUND),
|
|
}
|
|
canvas.fill_rect(Rect::new(
|
|
CELL_SIZE as i32 * x as i32 + BORDER_RADIUS as i32,
|
|
CELL_SIZE as i32 * y as i32 + BORDER_RADIUS as i32,
|
|
CELL_SIZE - 2 * BORDER_RADIUS,
|
|
CELL_SIZE - 2 * BORDER_RADIUS,
|
|
))?;
|
|
}
|
|
}
|
|
|
|
match self.hold_piece() {
|
|
Some(p) => {
|
|
canvas.set_draw_color(p);
|
|
canvas.fill_rect(Rect::new(-32 - UI_PADDING as i32, 0, CELL_SIZE, CELL_SIZE));
|
|
}
|
|
None => (),
|
|
}
|
|
|
|
match self.active_piece {
|
|
Some(piece) => piece.render(canvas)?,
|
|
None => (),
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
impl Renderable for Tetromino {
|
|
fn width(&self) -> usize {
|
|
CELL_SIZE as usize
|
|
* match self.rotation_state {
|
|
RotationState::O | RotationState::U => match self.piece_type {
|
|
TetrominoType::I => 4,
|
|
TetrominoType::O => 2,
|
|
_ => 3,
|
|
},
|
|
RotationState::L | RotationState::R => match self.piece_type {
|
|
TetrominoType::I => 1,
|
|
_ => 2,
|
|
},
|
|
}
|
|
}
|
|
|
|
fn height(&self) -> usize {
|
|
CELL_SIZE as usize
|
|
* match self.rotation_state {
|
|
RotationState::O | RotationState::U => match self.piece_type {
|
|
TetrominoType::I => 1,
|
|
_ => 2,
|
|
},
|
|
RotationState::L | RotationState::R => match self.piece_type {
|
|
TetrominoType::I => 4,
|
|
TetrominoType::O => 2,
|
|
_ => 3,
|
|
},
|
|
}
|
|
}
|
|
|
|
fn render<R: RenderTarget>(&self, canvas: &mut Canvas<R>) -> Result<(), String> {
|
|
for Position { x, y } in self.get_cur_occupied_spaces() {
|
|
canvas.set_draw_color::<MinoColor>(self.piece_type.into());
|
|
let height = y as isize - PLAYFIELD_HEIGHT as isize;
|
|
canvas.fill_rect(Rect::new(
|
|
CELL_SIZE as i32 * x as i32 + BORDER_RADIUS as i32,
|
|
CELL_SIZE as i32 * height as i32 + BORDER_RADIUS as i32,
|
|
CELL_SIZE - 2 * BORDER_RADIUS,
|
|
CELL_SIZE - 2 * BORDER_RADIUS,
|
|
))?;
|
|
}
|
|
Ok(())
|
|
}
|
|
}
|