diff --git a/src/game.rs b/src/game.rs index 29fa673..f089010 100644 --- a/src/game.rs +++ b/src/game.rs @@ -20,7 +20,7 @@ pub struct Game { rotation_system: SRS, level: u8, points: u32, - pub tick: u64, + tick: u64, next_gravity_tick: u64, next_lock_tick: u64, next_spawn_tick: u64, @@ -121,7 +121,7 @@ impl Renderable for Game { } } -trait Controllable { +pub trait Controllable { fn move_left(&mut self); fn move_up(&mut self); fn move_right(&mut self); @@ -133,13 +133,27 @@ trait Controllable { } impl Controllable for Game { - fn move_left(&mut self) {} - fn move_up(&mut self) {} - fn move_right(&mut self) {} - fn move_down(&mut self) {} - fn rotate_left(&mut self) {} - fn rotate_right(&mut self) {} - fn hard_drop(&mut self) {} + fn move_left(&mut self) { + self.playfield.move_offset(-1, 0); + } + fn move_up(&mut self) { + // self.playfield.move_up(); + } + fn move_right(&mut self) { + self.playfield.move_offset(1, 0); + } + fn move_down(&mut self) { + // self.playfield.move_down(); + } + fn rotate_left(&mut self) { + // self.playfield.rotate_left(); + } + fn rotate_right(&mut self) { + // self.playfield.rotate_right(); + } + fn hard_drop(&mut self) { + // self.playfield.hard_drop(); + } fn hold(&mut self) { // if self.can_swap_hold { diff --git a/src/main.rs b/src/main.rs index aea3f15..d26d502 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,4 +1,4 @@ -use game::{Game, Tickable}; +use game::{Controllable, Game, Tickable}; use graphics::COLOR_BACKGROUND; use sdl2::event::Event; use sdl2::keyboard::Keycode; @@ -30,7 +30,7 @@ async fn main() -> Result<(), Box> { let mut canvas = window.into_canvas().build()?; let mut event_pump = sdl_context.event_pump()?; let mut game = Game::default(); - let mut interval = interval(Duration::from_millis(60 / TICKS_PER_SECOND as u64)); + let mut interval = interval(Duration::from_millis(1000 / TICKS_PER_SECOND as u64)); 'running: while !game.is_game_over() { for event in event_pump.poll_iter() { @@ -40,6 +40,40 @@ async fn main() -> Result<(), Box> { keycode: Some(Keycode::Escape), .. } => break 'running, + Event::KeyDown { + keycode: Some(Keycode::Left), + .. + } => { + game.move_left(); + } + Event::KeyDown { + keycode: Some(Keycode::Right), + .. + } => game.move_right(), + Event::KeyDown { + keycode: Some(Keycode::Up), + .. + } => game.move_up(), + Event::KeyDown { + keycode: Some(Keycode::Down), + .. + } => game.move_down(), + Event::KeyDown { + keycode: Some(Keycode::Z), + .. + } => game.rotate_left(), + Event::KeyDown { + keycode: Some(Keycode::X), + .. + } => game.rotate_right(), + Event::KeyDown { + keycode: Some(Keycode::Space), + .. + } => game.hard_drop(), + Event::KeyDown { + keycode: Some(Keycode::LShift), + .. + } => game.hold(), _ => {} } } @@ -51,8 +85,5 @@ async fn main() -> Result<(), Box> { interval.tick().await; } - println!("Game over! Final game state:"); - dbg!(game); - Ok(()) } diff --git a/src/playfield.rs b/src/playfield.rs index 39125a8..d1921b4 100644 --- a/src/playfield.rs +++ b/src/playfield.rs @@ -97,6 +97,36 @@ impl PlayField { } } + pub fn move_offset(&mut self, x: isize, y: isize) -> bool { + if self.can_move_offset(x, y) { + match self.active_piece { + Some(mut piece) => { + piece.position.x = (x + piece.position.x as isize) as usize; + piece.position.y = (y + piece.position.y as isize) as usize; + self.active_piece = Some(piece); + true + } + None => panic!("Active piece missing!"), + } + } else { + false + } + } + + fn can_move_offset(&self, x: isize, y: isize) -> bool { + match self.active_piece { + Some(piece) => piece + .get_occupied_spaces(piece.position.offset(x, y)) + .iter() + .fold(true, |acc, pos| { + acc && pos.y < self.field.len() + && pos.x < PLAYFIELD_WIDTH + && self.field[pos.y as usize][pos.x as usize].is_none() + }), + None => false, + } + } + pub fn spawn_tetromino(&mut self) { self.active_piece = Some(Tetromino::from( self.next_pieces @@ -120,10 +150,14 @@ impl PlayField { pub fn can_active_piece_move_down(&self) -> bool { self.active_piece .and_then(|p| { - Some(p.get_next_occupied_spaces().iter().fold(true, |acc, pos| { - acc && pos.y < self.field.len() - && self.field[pos.y as usize][pos.x as usize].is_none() - })) + Some( + p.get_falling_occupied_spaces() + .iter() + .fold(true, |acc, pos| { + acc && pos.y < self.field.len() + && self.field[pos.y as usize][pos.x as usize].is_none() + }), + ) }) .unwrap_or_else(|| false) } diff --git a/src/tetromino.rs b/src/tetromino.rs index 15aff40..05821f3 100644 --- a/src/tetromino.rs +++ b/src/tetromino.rs @@ -105,7 +105,7 @@ impl Position { } } - fn offset(&self, x: isize, y: isize) -> Position { + pub fn offset(&self, x: isize, y: isize) -> Position { Self { x: (x + self.x as isize) as usize, y: (y + self.y as isize) as usize, @@ -129,14 +129,6 @@ impl Tetromino { } } - pub fn get_next_occupied_spaces(&self) -> Vec { - self.get_occupied_spaces(self.position.offset(0, 1)) - } - - pub fn get_cur_occupied_spaces(&self) -> Vec { - self.get_occupied_spaces(self.position) - } - pub fn get_color(&self) -> MinoColor { match self.piece_type { TetrominoType::I => MinoColor::Cyan, @@ -157,7 +149,15 @@ impl Tetromino { } } - fn get_occupied_spaces(&self, center: Position) -> Vec { + pub fn get_falling_occupied_spaces(&self) -> Vec { + self.get_occupied_spaces(self.position.offset(0, 1)) + } + + pub fn get_cur_occupied_spaces(&self) -> Vec { + self.get_occupied_spaces(self.position) + } + + pub fn get_occupied_spaces(&self, center: Position) -> Vec { let mut spaces = vec![center]; match self.piece_type { TetrominoType::I => match self.rotation_state {