current work

master
Edward Shen 2020-03-19 18:51:43 -04:00
parent 036953fd2c
commit 31daef03c7
Signed by: edward
GPG Key ID: F350507060ED6C90
5 changed files with 254 additions and 12 deletions

52
src/game.rs Normal file
View 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;
// }
}
}

View File

@ -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
View 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!();
}
}

View File

@ -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
View 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 }],
};