current work
This commit is contained in:
parent
036953fd2c
commit
31daef03c7
5 changed files with 254 additions and 12 deletions
52
src/game.rs
Normal file
52
src/game.rs
Normal file
|
@ -0,0 +1,52 @@
|
|||
// A game is a self-contained struct that holds everything that an instance of
|
||||
// Tetris needs to run, except for something to tick the time forward.
|
||||
|
||||
use crate::playfield::PlayField;
|
||||
use crate::srs::RotationSystem;
|
||||
use crate::srs::SRS;
|
||||
|
||||
pub struct Game<RS: RotationSystem> {
|
||||
playfield: PlayField,
|
||||
rotation_system: RS,
|
||||
level: u8,
|
||||
points: u64,
|
||||
}
|
||||
|
||||
trait PlayerControllable {
|
||||
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 hold(&mut self);
|
||||
}
|
||||
|
||||
impl<RS: RotationSystem> PlayerControllable for Game<RS> {
|
||||
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 hold(&mut self) {
|
||||
// if self.can_swap_hold {
|
||||
// match self.hold_piece {
|
||||
// None => {
|
||||
// self.hold_piece = Some(self.active_piece);
|
||||
// self.get_new_piece();
|
||||
// }
|
||||
// Some(piece) => {
|
||||
// self.hold_piece = Some(self.active_piece);
|
||||
// self.active_piece = piece;
|
||||
// self.reset_position();
|
||||
// }
|
||||
// }
|
||||
|
||||
// self.can_swap_hold = false;
|
||||
// }
|
||||
}
|
||||
}
|
|
@ -1,7 +1,10 @@
|
|||
mod game;
|
||||
mod playfield;
|
||||
mod random;
|
||||
mod srs;
|
||||
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub enum Tetrino {
|
||||
pub enum Tetromino {
|
||||
I,
|
||||
O,
|
||||
T,
|
||||
|
|
76
src/playfield.rs
Normal file
76
src/playfield.rs
Normal file
|
@ -0,0 +1,76 @@
|
|||
use crate::random::RandomSystem;
|
||||
use crate::Tetromino;
|
||||
use std::collections::VecDeque;
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
enum MinoColor {
|
||||
Cyan,
|
||||
Yellow,
|
||||
Purple,
|
||||
Green,
|
||||
Red,
|
||||
Blue,
|
||||
Orange,
|
||||
Gray,
|
||||
}
|
||||
|
||||
enum Movement {
|
||||
Rotate,
|
||||
Gravity,
|
||||
Translation,
|
||||
}
|
||||
|
||||
pub struct Position {
|
||||
x: u8,
|
||||
y: u8,
|
||||
}
|
||||
|
||||
pub struct PlayField {
|
||||
can_swap_hold: bool,
|
||||
hold_piece: Option<Tetromino>,
|
||||
field: [[Option<MinoColor>; 10]; 40], // access via y, x
|
||||
active_piece: Tetromino,
|
||||
active_pos: Position,
|
||||
bag: RandomSystem,
|
||||
next_pieces: VecDeque<Tetromino>,
|
||||
last_movement: Movement,
|
||||
}
|
||||
|
||||
impl PlayField {
|
||||
pub fn new() -> Self {
|
||||
let mut bag = RandomSystem::new();
|
||||
let active_piece = bag.get_tetrino();
|
||||
let mut next_pieces = VecDeque::with_capacity(3);
|
||||
for _ in 0..next_pieces.len() {
|
||||
next_pieces.push_back(bag.get_tetrino());
|
||||
}
|
||||
|
||||
PlayField {
|
||||
can_swap_hold: true,
|
||||
hold_piece: None,
|
||||
field: [[None; 10]; 40],
|
||||
active_piece,
|
||||
active_pos: Position { x: 0, y: 0 },
|
||||
bag,
|
||||
next_pieces,
|
||||
last_movement: Movement::Gravity,
|
||||
}
|
||||
}
|
||||
|
||||
fn get_new_piece(&mut self) {
|
||||
self.active_piece = self
|
||||
.next_pieces
|
||||
.pop_front()
|
||||
.expect("visible queue to be populated");
|
||||
self.next_pieces.push_back(self.bag.get_tetrino());
|
||||
self.reset_position();
|
||||
self.can_swap_hold = true;
|
||||
}
|
||||
|
||||
/// Place the current Tetromino at its default spawn position and
|
||||
/// orientation. Used for hold-swapping or spawning in a new piece.
|
||||
fn reset_position(&mut self) {
|
||||
self.last_movement = Movement::Gravity;
|
||||
unimplemented!();
|
||||
}
|
||||
}
|
|
@ -1,9 +1,9 @@
|
|||
use crate::Tetrino;
|
||||
use crate::Tetromino;
|
||||
use rand::{rngs::ThreadRng, seq::SliceRandom, thread_rng};
|
||||
|
||||
pub struct RandomSystem {
|
||||
rng: ThreadRng,
|
||||
bag: [Tetrino; 7],
|
||||
bag: [Tetromino; 7],
|
||||
cur_pos: usize,
|
||||
}
|
||||
|
||||
|
@ -12,12 +12,12 @@ impl RandomSystem {
|
|||
let rng = thread_rng();
|
||||
RandomSystem {
|
||||
rng: rng,
|
||||
bag: [Tetrino::I; 7],
|
||||
bag: [Tetromino::I; 7], // Default value, should get init on first get
|
||||
cur_pos: 0,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_tetrino(&mut self) -> Tetrino {
|
||||
pub fn get_tetrino(&mut self) -> Tetromino {
|
||||
if self.cur_pos == 0 {
|
||||
self.refresh_bag();
|
||||
}
|
||||
|
@ -28,13 +28,13 @@ impl RandomSystem {
|
|||
|
||||
fn refresh_bag(&mut self) {
|
||||
self.bag = [
|
||||
Tetrino::I,
|
||||
Tetrino::O,
|
||||
Tetrino::T,
|
||||
Tetrino::S,
|
||||
Tetrino::Z,
|
||||
Tetrino::J,
|
||||
Tetrino::L,
|
||||
Tetromino::I,
|
||||
Tetromino::O,
|
||||
Tetromino::T,
|
||||
Tetromino::S,
|
||||
Tetromino::Z,
|
||||
Tetromino::J,
|
||||
Tetromino::L,
|
||||
];
|
||||
self.bag.shuffle(&mut self.rng);
|
||||
self.cur_pos = 0;
|
||||
|
|
111
src/srs.rs
Normal file
111
src/srs.rs
Normal file
|
@ -0,0 +1,111 @@
|
|||
use crate::playfield::{PlayField, Position};
|
||||
use crate::Tetromino;
|
||||
|
||||
#[derive(Copy)]
|
||||
pub struct Offset {
|
||||
x: i8,
|
||||
y: i8,
|
||||
}
|
||||
|
||||
pub enum RotationDirection {
|
||||
Clockwise,
|
||||
AntiClockwise,
|
||||
}
|
||||
|
||||
pub trait RotationSystem {
|
||||
fn get_rotation_offset(
|
||||
piece: &Tetromino,
|
||||
center: &Position,
|
||||
direction: RotationDirection,
|
||||
playfield: &PlayField,
|
||||
) -> Option<Offset>;
|
||||
}
|
||||
|
||||
pub struct SRS {}
|
||||
|
||||
impl RotationSystem for SRS {
|
||||
fn get_rotation_offset(
|
||||
piece: &Tetromino,
|
||||
center: &Position,
|
||||
direction: RotationDirection,
|
||||
playfield: &PlayField,
|
||||
) -> Option<Offset> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Hash)]
|
||||
enum Rotation {
|
||||
O, // Spawn state
|
||||
R, // Right rotation: clockwise rotation from spawn state
|
||||
U, // Upside-down rotation: rotation after 2 left or right rotations from spawn state
|
||||
L, // Left rotation: counterclockwise rotation from spawn state
|
||||
}
|
||||
|
||||
struct OffsetData {
|
||||
O: Vec<Offset>,
|
||||
R: Vec<Offset>,
|
||||
U: Vec<Offset>,
|
||||
L: Vec<Offset>,
|
||||
}
|
||||
|
||||
impl OffsetData {
|
||||
pub fn apply_right_rotation() {}
|
||||
}
|
||||
|
||||
const JLSTZOffsetData: OffsetData = OffsetData {
|
||||
O: vec![Offset { x: 0, y: 0 }],
|
||||
R: vec![
|
||||
Offset { x: 0, y: 0 },
|
||||
Offset { x: 1, y: 0 },
|
||||
Offset { x: 1, y: -1 },
|
||||
Offset { x: 0, y: 2 },
|
||||
Offset { x: 1, y: 2 },
|
||||
],
|
||||
U: vec![Offset { x: 0, y: 0 }],
|
||||
L: vec![
|
||||
Offset { x: 0, y: 0 },
|
||||
Offset { x: -1, y: 0 },
|
||||
Offset { x: -1, y: -1 },
|
||||
Offset { x: 0, y: 2 },
|
||||
Offset { x: -1, y: 2 },
|
||||
],
|
||||
};
|
||||
|
||||
const IOffsetData: OffsetData = OffsetData {
|
||||
O: vec![
|
||||
Offset { x: 0, y: 0 },
|
||||
Offset { x: -1, y: 0 },
|
||||
Offset { x: 2, y: 0 },
|
||||
Offset { x: -1, y: 0 },
|
||||
Offset { x: 2, y: 0 },
|
||||
],
|
||||
R: vec![
|
||||
Offset { x: -1, y: 0 },
|
||||
Offset { x: 0, y: 0 },
|
||||
Offset { x: 0, y: 0 },
|
||||
Offset { x: 0, y: 1 },
|
||||
Offset { x: 0, y: -2 },
|
||||
],
|
||||
U: vec![
|
||||
Offset { x: -1, y: 1 },
|
||||
Offset { x: 1, y: 1 },
|
||||
Offset { x: -2, y: 1 },
|
||||
Offset { x: 1, y: 0 },
|
||||
Offset { x: -2, y: 0 },
|
||||
],
|
||||
L: vec![
|
||||
Offset { x: 0, y: 1 },
|
||||
Offset { x: 0, y: 1 },
|
||||
Offset { x: 0, y: 1 },
|
||||
Offset { x: 0, y: -1 },
|
||||
Offset { x: 0, y: 2 },
|
||||
],
|
||||
};
|
||||
|
||||
const OOffsetData: OffsetData = OffsetData {
|
||||
O: vec![Offset { x: 0, y: 0 }],
|
||||
R: vec![Offset { x: 0, y: -1 }],
|
||||
U: vec![Offset { x: -1, y: -1 }],
|
||||
L: vec![Offset { x: -1, y: 0 }],
|
||||
};
|
Loading…
Reference in a new issue