Przeglądaj źródła

完成基本功能

runningwater 1 rok temu
rodzic
commit
c4ceab6401
1 zmienionych plików z 105 dodań i 59 usunięć
  1. 105 59
      src/main.rs

+ 105 - 59
src/main.rs

@@ -29,7 +29,7 @@ struct Tetrimino {
     x: isize,
     y: usize,
     current_state: u8,
-    index: i8,
+    index: u8,
 }
 
 impl Tetrimino {
@@ -78,12 +78,12 @@ impl Tetrimino {
 }
 
 trait TetriminoGenerator {
-    fn new() -> Tetrimino;
+    fn new(index: u8) -> Tetrimino;
 }
 
 struct TetriminoI;
 impl TetriminoGenerator for TetriminoI {
-    fn new() -> Tetrimino {
+    fn new(index: u8) -> Tetrimino {
         Tetrimino {
             states: vec![
                 vec![
@@ -102,14 +102,14 @@ impl TetriminoGenerator for TetriminoI {
             x: 4,
             y: 0,
             current_state: 0,
-            index: -1,
+            index,
         }
     }
 }
 
 struct TetriminoJ;
 impl TetriminoGenerator for TetriminoJ {
-    fn new() -> Tetrimino {
+    fn new(index: u8) -> Tetrimino {
         Tetrimino {
             states: vec![
                 vec![
@@ -140,14 +140,14 @@ impl TetriminoGenerator for TetriminoJ {
             x: 4,
             y: 0,
             current_state: 0,
-            index: -1,
+            index,
         }
     }
 }
 
 struct TetriminoL;
 impl TetriminoGenerator for TetriminoL {
-    fn new() -> Tetrimino {
+    fn new(index: u8) -> Tetrimino {
         Tetrimino {
             states: vec![
                 vec![
@@ -178,14 +178,14 @@ impl TetriminoGenerator for TetriminoL {
             x: 4,
             y: 0,
             current_state: 0,
-            index: -1,
+            index,
         }
     }
 }
 
 struct TetriminoO;
 impl TetriminoGenerator for TetriminoO {
-    fn new() -> Tetrimino {
+    fn new(index: u8) -> Tetrimino {
         Tetrimino {
             states: vec![vec![
                 vec![4, 4, 0, 0],
@@ -196,14 +196,14 @@ impl TetriminoGenerator for TetriminoO {
             x: 5,
             y: 0,
             current_state: 0,
-            index: -1,
+            index,
         }
     }
 }
 
 struct TetriminoS;
 impl TetriminoGenerator for TetriminoS {
-    fn new() -> Tetrimino {
+    fn new(index: u8) -> Tetrimino {
         Tetrimino {
             states: vec![
                 vec![
@@ -222,14 +222,14 @@ impl TetriminoGenerator for TetriminoS {
             x: 4,
             y: 0,
             current_state: 0,
-            index: -1,
+            index,
         }
     }
 }
 
 struct TetriminoZ;
 impl TetriminoGenerator for TetriminoZ {
-    fn new() -> Tetrimino {
+    fn new(index: u8) -> Tetrimino {
         Tetrimino {
             states: vec![
                 vec![
@@ -248,14 +248,14 @@ impl TetriminoGenerator for TetriminoZ {
             x: 4,
             y: 0,
             current_state: 0,
-            index: -1,
+            index,
         }
     }
 }
 
 struct TetriminoT;
 impl TetriminoGenerator for TetriminoT {
-    fn new() -> Tetrimino {
+    fn new(index: u8) -> Tetrimino {
         Tetrimino {
             states: vec![
                 vec![
@@ -286,7 +286,7 @@ impl TetriminoGenerator for TetriminoT {
             x: 4,
             y: 0,
             current_state: 0,
-            index: -1,
+            index,
         }
     }
 }
@@ -297,6 +297,7 @@ struct Tetris {
     score: u32,
     nb_lines: u32,
     current_piece: Option<Tetrimino>,
+    next_piece: Option<Tetrimino>,
 }
 
 impl Tetris {
@@ -313,27 +314,32 @@ impl Tetris {
             score: 0,
             nb_lines: 0,
             current_piece: None,
+            next_piece: None,
         }
     }
     /// 随机创建 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;
+            if unsafe { PREV } == rand_nb {
+                rand_nb = rand::random::<u8>() % 7;
+            }
+            unsafe {
+                PREV = rand_nb;
+            }
         }
-        unsafe {
-            PREV = 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!(),
         }
     }
@@ -371,6 +377,7 @@ impl Tetris {
         }
     }
     fn make_permanent(&mut self) {
+        // println!("不能改变位置,已经到底");
         let mut to_add = 0u32;
         if let Some(ref mut piece) = self.current_piece {
             let mut shift_y = 0;
@@ -400,6 +407,9 @@ impl Tetris {
         self.update_score(to_add);
         self.check_lines();
         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) {
         self.score += to_add;
@@ -424,7 +434,7 @@ fn create_texture_rect<'a>(
         canvas
             .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,2));
+                texture.set_draw_color(Color::RGBA(r, g, b, 255));
                 texture.clear();
             })
             .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>(
     tetris: &Tetris,
-    mut canvas: &mut WindowCanvas,
+    canvas: &mut WindowCanvas,
     texture_creator: &'a TextureCreator<WindowContext>,
     font: &sdl2::ttf::Font,
     start_x_point: i32,
@@ -463,16 +473,7 @@ fn display_game_information<'a>(
     let score_text = format!("Score: {}", tetris.score);
     let lines_sent_text = format!("Lines sent: {}", tetris.nb_lines);
     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)
         .expect("Cannot render text");
@@ -481,6 +482,8 @@ fn display_game_information<'a>(
             .expect("Cannot render text");
     let level = create_texture_from_text(&texture_creator, &font, &level_text, 255, 255, 255)
         .expect("Cannot render text");
+    let next = create_texture_from_text(&texture_creator, &font, &next_preview, 255, 255, 255)
+        .expect("Cannot render text");
 
     canvas
         .copy(
@@ -503,19 +506,13 @@ fn display_game_information<'a>(
             get_rect_from_text(&level_text, start_x_point, 160),
         )
         .expect("Couldn't copy text");
-
     canvas
         .copy(
-            &border_preview,
+            &next,
             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 = [
-        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!(39, 218, 225),
         texture!(45, 216, 47),
         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 {
         if is_time_over(&tetris, &timer) {
             let mut make_permanent = false;
@@ -707,9 +715,15 @@ pub fn main() {
                 ),
             )
             .expect("Couldn't copy texture into window");
-        
+
         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) {
                 print_game_information(&tetris);
                 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 {
@@ -803,7 +849,7 @@ fn handle_events(
 ) -> bool {
     // The current tetrimino is still falling.
     // 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;
     if let Some(ref mut piece) = tetris.current_piece {
         let mut tmp_x = piece.x;