From 77d6ab3785a8fa8cc788b820ecea5097b2c7661b Mon Sep 17 00:00:00 2001 From: materus Date: Thu, 7 Mar 2024 22:57:21 +0000 Subject: [PATCH] Initial commit --- .gitignore | 1 + Cargo.lock | 126 ++++++++++++++++++++++++++++++++ Cargo.toml | 10 +++ src/main.rs | 204 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 341 insertions(+) create mode 100644 .gitignore create mode 100644 Cargo.lock create mode 100644 Cargo.toml create mode 100644 src/main.rs diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/target diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..e0130ad --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,126 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "cc" +version = "1.0.90" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8cd6604a82acf3039f1144f54b8eb34e91ffba622051189e71b781822d5ee1f5" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "cmake" +version = "0.1.50" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a31c789563b815f77f4250caee12365734369f942439b7defd71e18a48197130" +dependencies = [ + "cc", +] + +[[package]] +name = "fs_extra" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c" + +[[package]] +name = "getrandom" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "libc" +version = "0.2.153" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" + +[[package]] +name = "ppv-lite86" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "raylib" +version = "3.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb567269b7ea9ae3c4a5aab4dc95e0b4d8df2a49a25e1670a3bb17bc17504606" +dependencies = [ + "cfg-if", + "lazy_static", + "libc", + "raylib-sys", +] + +[[package]] +name = "raylib-sys" +version = "3.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20c97b5e251b73c52183914d4756104cab401050f244c19abe83fa05a4e86840" +dependencies = [ + "cc", + "cmake", + "fs_extra", +] + +[[package]] +name = "snake" +version = "0.1.0" +dependencies = [ + "rand", + "raylib", +] + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..c0c1347 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "snake" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +rand = "0.8.5" +raylib = "3.7.0" diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..d62c785 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,204 @@ +use raylib::prelude::*; +use rand::prelude::*; + +const WIDTH: i32 = 800; +const HEIGHT: i32 = 800; + +const RECT_SIZE: i32 = 20; + +const BOARD_HEIGHT: i32 = HEIGHT / RECT_SIZE; +const BOARD_WIDTH: i32 = WIDTH / RECT_SIZE; +#[derive(Copy, Clone)] +enum RectType { + HEAD, + BODY, + EMPTY, + APPLE, +} +#[derive(Copy, Clone)] +enum Direction { + TOP, + DOWN, + LEFT, + RIGHT, +} +#[derive(Copy, Clone, PartialEq)] +struct Position { + x: i32, + y: i32, +} +fn gen_apple(game_data: &GameData) -> Position { + let mut pos: Position = Position {x:0, y:0}; + let mut done = false; + while !done { + done = true; + pos = Position {x: thread_rng().gen_range(0..BOARD_WIDTH), y: thread_rng().gen_range(0..BOARD_HEIGHT)}; + if game_data.head == pos {done = false} + else { + for tail_seg in &game_data.tail + { + if (tail_seg.x == pos.x) && (tail_seg.y == pos.y) { + done = false; + break; + } + } + } + } + pos +} +struct GameData { + board: [RectType; (BOARD_HEIGHT * BOARD_HEIGHT) as usize], + head: Position, + tail: Vec, + direction: Direction, + last_direction: Direction, + game_over: bool, + score: u32, + apple: Position +} +fn update_game(game_data: &mut GameData) { + game_data.last_direction = game_data.direction; + let old_head_pos = game_data.head; + match game_data.direction { + Direction::DOWN => game_data.head.y += 1, + Direction::TOP => game_data.head.y -= 1, + Direction::LEFT => game_data.head.x -= 1, + Direction::RIGHT => game_data.head.x += 1, + } + if game_data.head.x >= BOARD_WIDTH { + game_data.head.x = 0 + } else if game_data.head.x < 0 { + game_data.head.x = BOARD_WIDTH - 1 + } else if game_data.head.y < 0 { + game_data.head.y = BOARD_HEIGHT - 1 + } else if game_data.head.y >= BOARD_HEIGHT { + game_data.head.y = 0 + } + if game_data.head == game_data.apple + { + game_data.apple = gen_apple(game_data); + game_data.score += 1; + game_data.tail.push(game_data.tail.last().copied().unwrap()); + } + + let last_tail = game_data.tail.last().copied().unwrap(); + for tail_id in (1..game_data.tail.len()).rev() { + game_data.tail[tail_id] = game_data.tail[tail_id - 1]; + if game_data.head == game_data.tail[tail_id] { + game_data.game_over = true; + } + game_data.board + [(game_data.tail[tail_id].x + game_data.tail[tail_id].y * BOARD_HEIGHT) as usize] = + RectType::BODY; + } + game_data.board[(last_tail.x + last_tail.y * BOARD_HEIGHT) as usize] = RectType::EMPTY; + game_data.tail[0] = old_head_pos; + game_data.board[(old_head_pos.x + old_head_pos.y * BOARD_HEIGHT) as usize] = RectType::BODY; + game_data.board[(game_data.head.x + game_data.head.y * BOARD_HEIGHT) as usize] = RectType::HEAD; + game_data.board[(game_data.apple.x + game_data.apple.y * BOARD_HEIGHT) as usize] = RectType::APPLE; + +} +fn create_game_data() -> GameData { + let mut game_data = GameData { + board: [RectType::EMPTY; (BOARD_HEIGHT * BOARD_WIDTH) as usize], + head: Position { + x: BOARD_WIDTH / 2, + y: BOARD_HEIGHT / 2, + }, + tail: vec![ + Position { + x: BOARD_WIDTH / 2, + y: BOARD_HEIGHT / 2, + }; + 3 + ], + direction: Direction::RIGHT, + last_direction: Direction::LEFT, + game_over: false, + score: 0, + apple: Position {x: 0, y: 0} + }; + game_data.apple = gen_apple(&game_data); + game_data +} +fn main() { + let (mut rl, thread) = raylib::init() + .size(WIDTH, HEIGHT) + .title("Snake") + .vsync() + .build(); + + let show_fps: bool = false; + + let mut time: f64 = 0.0; + let mut game_data = create_game_data(); + + while !rl.window_should_close() { + let fps = rl.get_fps(); + let frame_time = rl.get_frame_time(); + time += f64::from(frame_time); + + if (rl.is_key_down(KeyboardKey::KEY_UP) || rl.is_key_down(KeyboardKey::KEY_W)) + && !matches!(game_data.last_direction, Direction::DOWN) + { + game_data.direction = Direction::TOP + } + + if (rl.is_key_down(KeyboardKey::KEY_DOWN) || rl.is_key_down(KeyboardKey::KEY_S)) + && !matches!(game_data.last_direction, Direction::TOP) + { + game_data.direction = Direction::DOWN + } + if (rl.is_key_down(KeyboardKey::KEY_LEFT) || rl.is_key_down(KeyboardKey::KEY_A)) + && !matches!(game_data.last_direction, Direction::RIGHT) + { + game_data.direction = Direction::LEFT + } + if (rl.is_key_down(KeyboardKey::KEY_RIGHT) || rl.is_key_down(KeyboardKey::KEY_D)) + && !matches!(game_data.last_direction, Direction::LEFT) + { + game_data.direction = Direction::RIGHT + } + + if time >= 0.1 { + time = 0.0; + if !game_data.game_over { + update_game(&mut game_data); + }; + } + if rl.is_key_down(KeyboardKey::KEY_ENTER) && game_data.game_over { + game_data = create_game_data(); + time = 0.0; + } + + let mut d = rl.begin_drawing(&thread); + d.clear_background(Color::WHITE); + for y in 0..BOARD_HEIGHT { + for x in 0..BOARD_WIDTH { + let color: Color; + match game_data.board[(x + y * BOARD_WIDTH) as usize] { + RectType::HEAD => color = Color::GREEN, + RectType::BODY => color = Color::DARKGREEN, + RectType::APPLE => color = Color::RED, + RectType::EMPTY => color = Color::WHITE, + }; + d.draw_rectangle(x * RECT_SIZE, y * RECT_SIZE, RECT_SIZE, RECT_SIZE, color); + } + } + if game_data.game_over { + d.draw_text("Game Over", WIDTH / 2 - 100, HEIGHT / 2, 40, Color::BLACK); + d.draw_text( + format!("Score: {}", game_data.score).as_str(), + WIDTH / 2 - 50, + HEIGHT / 2 + 50, + 20, + Color::BLACK, + ); + d.draw_text("Press Enter", WIDTH / 2 - 40, HEIGHT / 2 + 75, 10, Color::BLACK); + + } + if show_fps { + d.draw_text(fps.to_string().as_str(), 20, 10, 20, Color::BLUE) + } + } +}