|
@@ -29,7 +29,7 @@ struct Tetrimino {
|
|
|
x: isize,
|
|
x: isize,
|
|
|
y: usize,
|
|
y: usize,
|
|
|
current_state: u8,
|
|
current_state: u8,
|
|
|
- index: i8,
|
|
|
|
|
|
|
+ index: u8,
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
impl Tetrimino {
|
|
impl Tetrimino {
|
|
@@ -78,12 +78,12 @@ impl Tetrimino {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
trait TetriminoGenerator {
|
|
trait TetriminoGenerator {
|
|
|
- fn new() -> Tetrimino;
|
|
|
|
|
|
|
+ fn new(index: u8) -> Tetrimino;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
struct TetriminoI;
|
|
struct TetriminoI;
|
|
|
impl TetriminoGenerator for TetriminoI {
|
|
impl TetriminoGenerator for TetriminoI {
|
|
|
- fn new() -> Tetrimino {
|
|
|
|
|
|
|
+ fn new(index: u8) -> Tetrimino {
|
|
|
Tetrimino {
|
|
Tetrimino {
|
|
|
states: vec![
|
|
states: vec![
|
|
|
vec![
|
|
vec![
|
|
@@ -102,14 +102,14 @@ impl TetriminoGenerator for TetriminoI {
|
|
|
x: 4,
|
|
x: 4,
|
|
|
y: 0,
|
|
y: 0,
|
|
|
current_state: 0,
|
|
current_state: 0,
|
|
|
- index: -1,
|
|
|
|
|
|
|
+ index,
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
struct TetriminoJ;
|
|
struct TetriminoJ;
|
|
|
impl TetriminoGenerator for TetriminoJ {
|
|
impl TetriminoGenerator for TetriminoJ {
|
|
|
- fn new() -> Tetrimino {
|
|
|
|
|
|
|
+ fn new(index: u8) -> Tetrimino {
|
|
|
Tetrimino {
|
|
Tetrimino {
|
|
|
states: vec![
|
|
states: vec![
|
|
|
vec![
|
|
vec![
|
|
@@ -140,14 +140,14 @@ impl TetriminoGenerator for TetriminoJ {
|
|
|
x: 4,
|
|
x: 4,
|
|
|
y: 0,
|
|
y: 0,
|
|
|
current_state: 0,
|
|
current_state: 0,
|
|
|
- index: -1,
|
|
|
|
|
|
|
+ index,
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
struct TetriminoL;
|
|
struct TetriminoL;
|
|
|
impl TetriminoGenerator for TetriminoL {
|
|
impl TetriminoGenerator for TetriminoL {
|
|
|
- fn new() -> Tetrimino {
|
|
|
|
|
|
|
+ fn new(index: u8) -> Tetrimino {
|
|
|
Tetrimino {
|
|
Tetrimino {
|
|
|
states: vec![
|
|
states: vec![
|
|
|
vec![
|
|
vec![
|
|
@@ -178,14 +178,14 @@ impl TetriminoGenerator for TetriminoL {
|
|
|
x: 4,
|
|
x: 4,
|
|
|
y: 0,
|
|
y: 0,
|
|
|
current_state: 0,
|
|
current_state: 0,
|
|
|
- index: -1,
|
|
|
|
|
|
|
+ index,
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
struct TetriminoO;
|
|
struct TetriminoO;
|
|
|
impl TetriminoGenerator for TetriminoO {
|
|
impl TetriminoGenerator for TetriminoO {
|
|
|
- fn new() -> Tetrimino {
|
|
|
|
|
|
|
+ fn new(index: u8) -> Tetrimino {
|
|
|
Tetrimino {
|
|
Tetrimino {
|
|
|
states: vec![vec![
|
|
states: vec![vec![
|
|
|
vec![4, 4, 0, 0],
|
|
vec![4, 4, 0, 0],
|
|
@@ -196,14 +196,14 @@ impl TetriminoGenerator for TetriminoO {
|
|
|
x: 5,
|
|
x: 5,
|
|
|
y: 0,
|
|
y: 0,
|
|
|
current_state: 0,
|
|
current_state: 0,
|
|
|
- index: -1,
|
|
|
|
|
|
|
+ index,
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
struct TetriminoS;
|
|
struct TetriminoS;
|
|
|
impl TetriminoGenerator for TetriminoS {
|
|
impl TetriminoGenerator for TetriminoS {
|
|
|
- fn new() -> Tetrimino {
|
|
|
|
|
|
|
+ fn new(index: u8) -> Tetrimino {
|
|
|
Tetrimino {
|
|
Tetrimino {
|
|
|
states: vec![
|
|
states: vec![
|
|
|
vec![
|
|
vec![
|
|
@@ -222,14 +222,14 @@ impl TetriminoGenerator for TetriminoS {
|
|
|
x: 4,
|
|
x: 4,
|
|
|
y: 0,
|
|
y: 0,
|
|
|
current_state: 0,
|
|
current_state: 0,
|
|
|
- index: -1,
|
|
|
|
|
|
|
+ index,
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
struct TetriminoZ;
|
|
struct TetriminoZ;
|
|
|
impl TetriminoGenerator for TetriminoZ {
|
|
impl TetriminoGenerator for TetriminoZ {
|
|
|
- fn new() -> Tetrimino {
|
|
|
|
|
|
|
+ fn new(index: u8) -> Tetrimino {
|
|
|
Tetrimino {
|
|
Tetrimino {
|
|
|
states: vec![
|
|
states: vec![
|
|
|
vec![
|
|
vec![
|
|
@@ -248,14 +248,14 @@ impl TetriminoGenerator for TetriminoZ {
|
|
|
x: 4,
|
|
x: 4,
|
|
|
y: 0,
|
|
y: 0,
|
|
|
current_state: 0,
|
|
current_state: 0,
|
|
|
- index: -1,
|
|
|
|
|
|
|
+ index,
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
struct TetriminoT;
|
|
struct TetriminoT;
|
|
|
impl TetriminoGenerator for TetriminoT {
|
|
impl TetriminoGenerator for TetriminoT {
|
|
|
- fn new() -> Tetrimino {
|
|
|
|
|
|
|
+ fn new(index: u8) -> Tetrimino {
|
|
|
Tetrimino {
|
|
Tetrimino {
|
|
|
states: vec![
|
|
states: vec![
|
|
|
vec![
|
|
vec![
|
|
@@ -286,7 +286,7 @@ impl TetriminoGenerator for TetriminoT {
|
|
|
x: 4,
|
|
x: 4,
|
|
|
y: 0,
|
|
y: 0,
|
|
|
current_state: 0,
|
|
current_state: 0,
|
|
|
- index: -1,
|
|
|
|
|
|
|
+ index,
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
@@ -297,6 +297,7 @@ struct Tetris {
|
|
|
score: u32,
|
|
score: u32,
|
|
|
nb_lines: u32,
|
|
nb_lines: u32,
|
|
|
current_piece: Option<Tetrimino>,
|
|
current_piece: Option<Tetrimino>,
|
|
|
|
|
+ next_piece: Option<Tetrimino>,
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
impl Tetris {
|
|
impl Tetris {
|
|
@@ -313,27 +314,32 @@ impl Tetris {
|
|
|
score: 0,
|
|
score: 0,
|
|
|
nb_lines: 0,
|
|
nb_lines: 0,
|
|
|
current_piece: None,
|
|
current_piece: None,
|
|
|
|
|
+ next_piece: None,
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
/// 随机创建 tetrimino
|
|
/// 随机创建 tetrimino
|
|
|
- fn create_new_tetrimino(&self) -> Tetrimino {
|
|
|
|
|
- static mut PREV: u8 = 7;
|
|
|
|
|
- let mut rand_nb = rand::random::<u8>() % 7;
|
|
|
|
|
- if unsafe { PREV } == rand_nb {
|
|
|
|
|
|
|
+ fn create_new_tetrimino(&self, cache_nb: u8) -> Tetrimino {
|
|
|
|
|
+ let mut rand_nb: u8;
|
|
|
|
|
+ if cache_nb != 255 {
|
|
|
|
|
+ rand_nb = cache_nb;
|
|
|
|
|
+ } else {
|
|
|
|
|
+ static mut PREV: u8 = 7;
|
|
|
rand_nb = rand::random::<u8>() % 7;
|
|
rand_nb = rand::random::<u8>() % 7;
|
|
|
|
|
+ if unsafe { PREV } == rand_nb {
|
|
|
|
|
+ rand_nb = rand::random::<u8>() % 7;
|
|
|
|
|
+ }
|
|
|
|
|
+ unsafe {
|
|
|
|
|
+ PREV = rand_nb;
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
- unsafe {
|
|
|
|
|
- PREV = rand_nb;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
match rand_nb {
|
|
match rand_nb {
|
|
|
- 0 => TetriminoI::new(),
|
|
|
|
|
- 1 => TetriminoJ::new(),
|
|
|
|
|
- 2 => TetriminoL::new(),
|
|
|
|
|
- 3 => TetriminoO::new(),
|
|
|
|
|
- 4 => TetriminoS::new(),
|
|
|
|
|
- 5 => TetriminoZ::new(),
|
|
|
|
|
- 6 => TetriminoT::new(),
|
|
|
|
|
|
|
+ 0 => TetriminoI::new(rand_nb),
|
|
|
|
|
+ 1 => TetriminoJ::new(rand_nb),
|
|
|
|
|
+ 2 => TetriminoL::new(rand_nb),
|
|
|
|
|
+ 3 => TetriminoO::new(rand_nb),
|
|
|
|
|
+ 4 => TetriminoS::new(rand_nb),
|
|
|
|
|
+ 5 => TetriminoZ::new(rand_nb),
|
|
|
|
|
+ 6 => TetriminoT::new(rand_nb),
|
|
|
_ => unreachable!(),
|
|
_ => unreachable!(),
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
@@ -371,6 +377,7 @@ impl Tetris {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
fn make_permanent(&mut self) {
|
|
fn make_permanent(&mut self) {
|
|
|
|
|
+ // println!("不能改变位置,已经到底");
|
|
|
let mut to_add = 0u32;
|
|
let mut to_add = 0u32;
|
|
|
if let Some(ref mut piece) = self.current_piece {
|
|
if let Some(ref mut piece) = self.current_piece {
|
|
|
let mut shift_y = 0;
|
|
let mut shift_y = 0;
|
|
@@ -400,6 +407,9 @@ impl Tetris {
|
|
|
self.update_score(to_add);
|
|
self.update_score(to_add);
|
|
|
self.check_lines();
|
|
self.check_lines();
|
|
|
self.current_piece = None;
|
|
self.current_piece = None;
|
|
|
|
|
+ // 生成下一个
|
|
|
|
|
+ self.next_piece = Some(self.create_new_tetrimino(255));
|
|
|
|
|
+ // println!("生成下一个: {}", self.next_piece.as_ref().unwrap().index);
|
|
|
}
|
|
}
|
|
|
fn update_score(&mut self, to_add: u32) {
|
|
fn update_score(&mut self, to_add: u32) {
|
|
|
self.score += to_add;
|
|
self.score += to_add;
|
|
@@ -424,7 +434,7 @@ fn create_texture_rect<'a>(
|
|
|
canvas
|
|
canvas
|
|
|
.with_texture_canvas(&mut square_texture, |texture| {
|
|
.with_texture_canvas(&mut square_texture, |texture| {
|
|
|
// texture.set_draw_color(Color::RGBA(r, g, b,rand::random::<u8>() % 254 + 1));
|
|
// texture.set_draw_color(Color::RGBA(r, g, b,rand::random::<u8>() % 254 + 1));
|
|
|
- texture.set_draw_color(Color::RGBA(r, g, b,2));
|
|
|
|
|
|
|
+ texture.set_draw_color(Color::RGBA(r, g, b, 255));
|
|
|
texture.clear();
|
|
texture.clear();
|
|
|
})
|
|
})
|
|
|
.expect("Failed to color a texture");
|
|
.expect("Failed to color a texture");
|
|
@@ -455,7 +465,7 @@ fn get_rect_from_text(text: &str, x: i32, y: i32) -> Option<Rect> {
|
|
|
|
|
|
|
|
fn display_game_information<'a>(
|
|
fn display_game_information<'a>(
|
|
|
tetris: &Tetris,
|
|
tetris: &Tetris,
|
|
|
- mut canvas: &mut WindowCanvas,
|
|
|
|
|
|
|
+ canvas: &mut WindowCanvas,
|
|
|
texture_creator: &'a TextureCreator<WindowContext>,
|
|
texture_creator: &'a TextureCreator<WindowContext>,
|
|
|
font: &sdl2::ttf::Font,
|
|
font: &sdl2::ttf::Font,
|
|
|
start_x_point: i32,
|
|
start_x_point: i32,
|
|
@@ -463,16 +473,7 @@ fn display_game_information<'a>(
|
|
|
let score_text = format!("Score: {}", tetris.score);
|
|
let score_text = format!("Score: {}", tetris.score);
|
|
|
let lines_sent_text = format!("Lines sent: {}", tetris.nb_lines);
|
|
let lines_sent_text = format!("Lines sent: {}", tetris.nb_lines);
|
|
|
let level_text = format!("Level: {}", tetris.current_level);
|
|
let level_text = format!("Level: {}", tetris.current_level);
|
|
|
- let border_preview = create_texture_rect(
|
|
|
|
|
- &mut canvas,
|
|
|
|
|
- &texture_creator,
|
|
|
|
|
- 255,
|
|
|
|
|
- 255,
|
|
|
|
|
- 255,
|
|
|
|
|
- TETRIS_HEIGHT as u32 * 4 + 20,
|
|
|
|
|
- TETRIS_HEIGHT as u32 * 10 + 20,
|
|
|
|
|
- )
|
|
|
|
|
- .expect("Failed to create a texture");
|
|
|
|
|
|
|
+ let next_preview = String::from("Next: ");
|
|
|
|
|
|
|
|
let score = create_texture_from_text(&texture_creator, &font, &score_text, 255, 255, 255)
|
|
let score = create_texture_from_text(&texture_creator, &font, &score_text, 255, 255, 255)
|
|
|
.expect("Cannot render text");
|
|
.expect("Cannot render text");
|
|
@@ -481,6 +482,8 @@ fn display_game_information<'a>(
|
|
|
.expect("Cannot render text");
|
|
.expect("Cannot render text");
|
|
|
let level = create_texture_from_text(&texture_creator, &font, &level_text, 255, 255, 255)
|
|
let level = create_texture_from_text(&texture_creator, &font, &level_text, 255, 255, 255)
|
|
|
.expect("Cannot render text");
|
|
.expect("Cannot render text");
|
|
|
|
|
+ let next = create_texture_from_text(&texture_creator, &font, &next_preview, 255, 255, 255)
|
|
|
|
|
+ .expect("Cannot render text");
|
|
|
|
|
|
|
|
canvas
|
|
canvas
|
|
|
.copy(
|
|
.copy(
|
|
@@ -503,19 +506,13 @@ fn display_game_information<'a>(
|
|
|
get_rect_from_text(&level_text, start_x_point, 160),
|
|
get_rect_from_text(&level_text, start_x_point, 160),
|
|
|
)
|
|
)
|
|
|
.expect("Couldn't copy text");
|
|
.expect("Couldn't copy text");
|
|
|
-
|
|
|
|
|
canvas
|
|
canvas
|
|
|
.copy(
|
|
.copy(
|
|
|
- &border_preview,
|
|
|
|
|
|
|
+ &next,
|
|
|
None,
|
|
None,
|
|
|
- Rect::new(
|
|
|
|
|
- start_x_point,
|
|
|
|
|
- 195,
|
|
|
|
|
- TETRIS_HEIGHT_MINI as u32 * 4 + 20,
|
|
|
|
|
- TETRIS_HEIGHT_MINI as u32 * 10 + 20,
|
|
|
|
|
- ),
|
|
|
|
|
|
|
+ get_rect_from_text(&level_text, start_x_point, 195),
|
|
|
)
|
|
)
|
|
|
- .expect("Couldn't copy canvas");
|
|
|
|
|
|
|
+ .expect("Couldn't copy text");
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/// # 写入文件
|
|
/// # 写入文件
|
|
@@ -654,16 +651,27 @@ pub fn main() {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
let textures = [
|
|
let textures = [
|
|
|
- texture!(255, 69, 69),
|
|
|
|
|
- texture!(255, 220, 69),
|
|
|
|
|
- texture!(237, 150, 37),
|
|
|
|
|
- texture!(171, 99, 237),
|
|
|
|
|
|
|
+ texture!(255, 215, 0),
|
|
|
|
|
+ texture!(34, 139, 34),
|
|
|
|
|
+ texture!(135, 206, 235),
|
|
|
|
|
+ texture!(201, 105, 30),
|
|
|
texture!(77, 149, 239),
|
|
texture!(77, 149, 239),
|
|
|
texture!(39, 218, 225),
|
|
texture!(39, 218, 225),
|
|
|
texture!(45, 216, 47),
|
|
texture!(45, 216, 47),
|
|
|
texture!(255, 255, 255),
|
|
texture!(255, 255, 255),
|
|
|
];
|
|
];
|
|
|
|
|
|
|
|
|
|
+ let next_preview_texture = create_texture_rect(
|
|
|
|
|
+ &mut canvas,
|
|
|
|
|
+ &texture_creator,
|
|
|
|
|
+ 135,
|
|
|
|
|
+ 206,
|
|
|
|
|
+ 235,
|
|
|
|
|
+ TETRIS_HEIGHT_MINI as u32,
|
|
|
|
|
+ TETRIS_HEIGHT_MINI as u32,
|
|
|
|
|
+ )
|
|
|
|
|
+ .expect("Couldn't create next_texture");
|
|
|
|
|
+
|
|
|
loop {
|
|
loop {
|
|
|
if is_time_over(&tetris, &timer) {
|
|
if is_time_over(&tetris, &timer) {
|
|
|
let mut make_permanent = false;
|
|
let mut make_permanent = false;
|
|
@@ -707,9 +715,15 @@ pub fn main() {
|
|
|
),
|
|
),
|
|
|
)
|
|
)
|
|
|
.expect("Couldn't copy texture into window");
|
|
.expect("Couldn't copy texture into window");
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
if tetris.current_piece.is_none() {
|
|
if tetris.current_piece.is_none() {
|
|
|
- let current_piece = tetris.create_new_tetrimino();
|
|
|
|
|
|
|
+ let current_piece;
|
|
|
|
|
+ if !tetris.next_piece.is_none() {
|
|
|
|
|
+ let i: u8 = tetris.next_piece.as_ref().unwrap().index;
|
|
|
|
|
+ current_piece = tetris.create_new_tetrimino(i);
|
|
|
|
|
+ } else {
|
|
|
|
|
+ current_piece = tetris.create_new_tetrimino(255);
|
|
|
|
|
+ }
|
|
|
if !current_piece.test_current_position(&tetris.game_map) {
|
|
if !current_piece.test_current_position(&tetris.game_map) {
|
|
|
print_game_information(&tetris);
|
|
print_game_information(&tetris);
|
|
|
break;
|
|
break;
|
|
@@ -747,6 +761,38 @@ pub fn main() {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+ // We need to draw our next tetrimino in here.
|
|
|
|
|
+ if let Some(ref mut piece) = tetris.next_piece {
|
|
|
|
|
+ for (line_bn, line) in piece.states[piece.current_state as usize]
|
|
|
|
|
+ .iter()
|
|
|
|
|
+ .enumerate()
|
|
|
|
|
+ {
|
|
|
|
|
+ for (case_nb, case) in line.iter().enumerate() {
|
|
|
|
|
+ if *case == 0 {
|
|
|
|
|
+ continue;
|
|
|
|
|
+ }
|
|
|
|
|
+ // The new part is here
|
|
|
|
|
+ canvas
|
|
|
|
|
+ .copy(
|
|
|
|
|
+ &next_preview_texture,
|
|
|
|
|
+ None,
|
|
|
|
|
+ Rect::new(
|
|
|
|
|
+ (TETRIS_HEIGHT as u32 * 8 + grid_x as u32) as i32
|
|
|
|
|
+ + 30 // 每个字符 10(3 个)
|
|
|
|
|
+ + (piece.x + case_nb as isize) as i32
|
|
|
|
|
+ * TETRIS_HEIGHT_MINI as i32,
|
|
|
|
|
+ (TETRIS_HEIGHT as u32 * 5 + grid_y as u32) as i32
|
|
|
|
|
+ + (piece.y + line_bn) as i32 * TETRIS_HEIGHT_MINI as i32,
|
|
|
|
|
+ TETRIS_HEIGHT_MINI as u32,
|
|
|
|
|
+ TETRIS_HEIGHT_MINI as u32,
|
|
|
|
|
+ ),
|
|
|
|
|
+ )
|
|
|
|
|
+ .expect("Couldn't copy texture into window");
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ // println!("grid_y: {}",grid_y);
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
if quit {
|
|
if quit {
|
|
@@ -803,7 +849,7 @@ fn handle_events(
|
|
|
) -> bool {
|
|
) -> bool {
|
|
|
// The current tetrimino is still falling.
|
|
// The current tetrimino is still falling.
|
|
|
// If not, then it becomes true, the tetrimino is then put into
|
|
// If not, then it becomes true, the tetrimino is then put into
|
|
|
- // the game map and we generate a new one.
|
|
|
|
|
|
|
+ // the game map. we generate a new one.
|
|
|
let mut make_permanent = false;
|
|
let mut make_permanent = false;
|
|
|
if let Some(ref mut piece) = tetris.current_piece {
|
|
if let Some(ref mut piece) = tetris.current_piece {
|
|
|
let mut tmp_x = piece.x;
|
|
let mut tmp_x = piece.x;
|