runningwater 1 rok pred
rodič
commit
9cc99660fd
2 zmenil súbory, kde vykonal 172 pridanie a 9 odobranie
  1. 2 0
      Cargo.toml
  2. 170 9
      src/main.rs

+ 2 - 0
Cargo.toml

@@ -7,3 +7,5 @@ edition = "2021"
 
 [dependencies]
 sdl2 = "0.36.0"
+[features]
+#default = ["sdl2/image"]

+ 170 - 9
src/main.rs

@@ -1,29 +1,161 @@
 extern crate sdl2;
 
+use std::fs::File;
+use std::io::{Read, Write};
+use std::time::{Duration, SystemTime};
+use std::{io, thread};
+
 use sdl2::event::Event;
 use sdl2::keyboard::Keycode;
 use sdl2::pixels::Color;
-use std::time::Duration;
+use sdl2::rect::Rect;
+use sdl2::render::{Texture, TextureCreator, WindowCanvas};
+use sdl2::video::WindowContext;
+
+// Crate a texture with 32x32 size
+const TEXTURE_SIZE: u32 = 32;
+const SCORE_FILE_NAME: &str = "scores.txt";
+
+#[derive(Clone, Copy)]
+enum TextureColor {
+    Green,
+    Blue,
+}
+
+fn create_texture_rect<'a>(
+    canvas: &mut WindowCanvas,
+    texture_creator: &'a TextureCreator<WindowContext>,
+    color: TextureColor,
+    size: u32,
+) -> Option<Texture<'a>> {
+    if let Ok(mut square_texture) = texture_creator.create_texture_target(None, size, size) {
+        canvas
+            .with_texture_canvas(&mut square_texture, |texture| {
+                match color {
+                    TextureColor::Green => texture.set_draw_color(Color::RGB(0, 255, 0)),
+                    TextureColor::Blue => texture.set_draw_color(Color::RGB(0, 0, 255)),
+                }
+                texture.clear();
+            })
+            .expect("Failed to color a texture");
+        Some(square_texture)
+    } else {
+        None
+    }
+}
+
+/// # 写入文件
+/// @content 内容
+///
+/// @file_name 文件名
+fn write_into_file(content: &str, file_name: &str) -> io::Result<()> {
+    let mut f = File::create(file_name)?;
+    f.write_all(content.as_bytes())
+}
+
+/// # 读取文件内容
+///  file_name 文件名
+///
+///  Return io::Result<String>
+fn read_from_file(file_name: &str) -> io::Result<String> {
+    let mut f = File::open(file_name)?;
+    let mut content = String::new();
+    f.read_to_string(&mut content)?;
+    Ok(content)
+}
+
+/// To keep things simple, we'll have a very simple file format:
+///
+/// 1. On the fire line, we store the best scores
+///
+/// 2. On the second line, we store the highest number of lines.
+fn slice_to_string(slice: &[u32]) -> String {
+    slice
+        .iter()
+        .map(|highscore| highscore.to_string())
+        .collect::<Vec<String>>()
+        .join(" ")
+}
+fn save_highscore_and_lines(highscores: &[u32], number_of_lines: &[u32]) -> bool {
+    let s_highscores = slice_to_string(highscores);
+    let s_number_of_lines = slice_to_string(number_of_lines);
+    write_into_file(
+        &*format!("{}\n{}\n", s_highscores, s_number_of_lines),
+        SCORE_FILE_NAME,
+    )
+    .is_ok()
+}
+/// # Reading formatted data from files
+fn line_to_slice(line: &str) -> Vec<u32> {
+    line.split(" ")
+        .filter_map(|nb| nb.parse::<u32>().ok())
+        .collect()
+}
+fn load_highscores_and_lines() -> Option<(Vec<u32>, Vec<u32>)> {
+    if let Ok(content) = read_from_file(SCORE_FILE_NAME) {
+        let mut lines = content
+            .splitn(2, "\n")
+            .map(|line| line_to_slice(line))
+            .collect::<Vec<_>>();
+
+        if lines.len() == 2 {
+            let (number_lines, hightscores) = (lines.pop().unwrap(), lines.pop().unwrap());
+            Some((hightscores, number_lines))
+        } else {
+            None
+        }
+    } else {
+        None
+    }
+}
 
 pub fn main() {
     let sdl_context = sdl2::init().expect("SDL init failed");
     let video_subsystem = sdl_context.video().expect("Couldn't get video subsystem");
 
+    // Parameters are: title, width, height
     let window = video_subsystem
         .window("rust-sdl2 demo", 800, 600)
-        .position_centered()
-        .build()
+        .position_centered() // to put it in the middle of the screen
+        .build() // to create the window
         .unwrap();
 
-    let mut canvas = window.into_canvas().build().expect("Failed to get SDL event pump");
+    let mut canvas = window
+        .into_canvas()
+        .target_texture()
+        .present_vsync() // To enable v-sync.
+        .build()
+        .expect("Failed to get SDL event pump");
 
-    canvas.set_draw_color(Color::RGB(255, 0, 0));
-    canvas.clear();
-    canvas.present();
-    let mut event_pump = sdl_context.event_pump().unwrap();
+    let texture_creator: TextureCreator<_> = canvas.texture_creator();
+
+    // Web create a texture with a 32x32 size.
+    let green_square = create_texture_rect(
+        &mut canvas,
+        &texture_creator,
+        TextureColor::Green,
+        TEXTURE_SIZE,
+    )
+    .expect("Failed to create a texture");
+
+    let blue_square = create_texture_rect(
+        &mut canvas,
+        &texture_creator,
+        TextureColor::Blue,
+        TEXTURE_SIZE,
+    )
+    .expect("Failed to create a texture");
+
+    let timer = SystemTime::now();
+
+    let mut event_pump = sdl_context
+        .event_pump()
+        .expect("Failed to get SDL event pump");
     'running: loop {
         for event in event_pump.poll_iter() {
             match event {
+                // If we receive a 'quit' event or if the user press the
+                // 'ESC' key, we quit.
                 Event::Quit { .. }
                 | Event::KeyDown {
                     keycode: Some(Keycode::Escape),
@@ -33,7 +165,36 @@ pub fn main() {
             }
         }
         // The rest of the game loop goes here...
+        canvas.set_draw_color(Color::RGB(255, 0, 0));
+        // We draw it
+        canvas.clear();
+
+        // The rectangle switch happens here:
+        let display_green = match timer.elapsed() {
+            Ok(elapsed) => elapsed.as_secs() % 2 == 0,
+            Err(_) => {
+                // In case of error, we do nothing
+                true
+            }
+        };
+        let square_texture = if display_green {
+            &green_square
+        } else {
+            &blue_square
+        };
+        // Copy our texture into the window.
+        canvas
+            .copy(
+                &square_texture,
+                None,
+                Rect::new(0, 0, TEXTURE_SIZE, TEXTURE_SIZE),
+            )
+            .expect("Couldn't copy texture in to window");
+        // We update window's display
+        canvas.present();
 
-        ::std::thread::sleep(Duration::new(0, 1_000_000_000u32 / 60));
+        // We sleep enough to get ~60 fps. If we don't call this,
+        // the program will take 100% of a CPU time.
+        thread::sleep(Duration::new(0, 1_000_000_000u32 / 60));
     }
 }