commit 7d882209602fcf7eadaf79043aa1a667e94b28a7 Author: kirbylife Date: Fri Jul 10 19:47:42 2020 -0500 Initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2330914 --- /dev/null +++ b/.gitignore @@ -0,0 +1,17 @@ +# Created by https://www.toptal.com/developers/gitignore/api/rust +# Edit at https://www.toptal.com/developers/gitignore?templates=rust + +### Rust ### +# Generated by Cargo +# will have compiled files and executables +/target/ + +# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries +# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html +Cargo.lock + +# These are backup files generated by rustfmt +**/*.rs.bk + +# End of https://www.toptal.com/developers/gitignore/api/rust + diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..36efca0 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "afusnakec" +version = "0.1.0" +authors = ["kirbylife "] +edition = "2018" + +[dependencies] +ggez = "0.5" +rand = "0.7.3" diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..d52f2ff --- /dev/null +++ b/src/main.rs @@ -0,0 +1,163 @@ +use ggez; +use ggez::event; +use ggez::event::KeyCode; +use ggez::graphics; +use ggez::input; +use ggez::nalgebra as na; +use ggez::{Context, GameResult}; +use rand::Rng; + +pub fn main() -> GameResult { + let cb = ggez::ContextBuilder::new("AFUSnakeC", "ggez"); + let (ctx, event_loop) = &mut cb.build()?; + let state = &mut MainState::new()?; + event::run(ctx, event_loop, state) +} + +#[derive(PartialEq)] +enum Direction { + UP, + DOWN, + LEFT, + RIGHT, +} + +struct Snake { + nodes: Vec<(i32, i32)>, + direction: Direction, +} + +impl Snake { + fn new() -> Self { + let mut nodes: Vec<(i32, i32)> = vec![]; + + let mut rng = rand::thread_rng(); + let start: (i32, i32) = (rng.gen_range(0, 80), rng.gen_range(0, 60)); + + for n in 0..50 { + nodes.push((start.0 - (n), start.1)); + } + Snake { + nodes: nodes, + direction: Direction::RIGHT, + } + } +} + +struct Fruit(i32, i32); + +impl Fruit { + fn new() -> Self { + let mut rng = rand::thread_rng(); + Fruit(rng.gen_range(0, 80), rng.gen_range(0, 60)) + } +} + +struct MainState { + snake: Snake, + fruit: Fruit, +} + +impl MainState { + fn new() -> GameResult { + let s = MainState { + snake: Snake::new(), + fruit: Fruit::new(), + }; + Ok(s) + } +} + +impl event::EventHandler for MainState { + fn update(&mut self, ctx: &mut Context) -> GameResult { + // Move the snake + // Remove the last node (the tail) + if self.snake.nodes.contains(&(self.fruit.0, self.fruit.1)) { + self.fruit = Fruit::new(); + } else { + self.snake.nodes.pop().unwrap(); + } + + let head = self.snake.nodes[0]; + + let vector: (i32, i32) = match self.snake.direction { + Direction::RIGHT => (1, 0), + Direction::LEFT => (-1, 0), + Direction::UP => (0, -1), + Direction::DOWN => (0, 1), + }; + + let mut tail = ((head.0 + vector.0) % 80, (head.1 + vector.1) % 60); + if tail.0 < 0 { + tail.0 += 79; + } + if tail.1 < 0 { + tail.1 += 59; + } + + if self.snake.nodes.contains(&tail) { + self.snake = Snake::new(); + self.fruit = Fruit::new(); + } else { + self.snake.nodes.insert(0, tail); + } + + // Change the direction in function of the key pressed + use input::keyboard; + + if keyboard::is_key_pressed(ctx, KeyCode::Right) { + if [Direction::UP, Direction::DOWN].contains(&self.snake.direction) { + self.snake.direction = Direction::RIGHT; + } + } else if keyboard::is_key_pressed(ctx, KeyCode::Left) { + if [Direction::UP, Direction::DOWN].contains(&self.snake.direction) { + self.snake.direction = Direction::LEFT; + } + } else if keyboard::is_key_pressed(ctx, KeyCode::Up) { + if [Direction::LEFT, Direction::RIGHT].contains(&self.snake.direction) { + self.snake.direction = Direction::UP; + } + } else if keyboard::is_key_pressed(ctx, KeyCode::Down) { + if [Direction::LEFT, Direction::RIGHT].contains(&self.snake.direction) { + self.snake.direction = Direction::DOWN; + } + } + + Ok(()) + } + + fn draw(&mut self, ctx: &mut Context) -> GameResult { + graphics::clear(ctx, [0.1, 0.2, 0.3, 1.0].into()); + + for node in self.snake.nodes.iter() { + let node = graphics::Mesh::new_rectangle( + ctx, + graphics::DrawMode::fill(), + graphics::Rect { + x: node.0 as f32 * 10.0, + y: node.1 as f32 * 10.0, + h: 10.0, + w: 10.0, + }, + graphics::WHITE, + )?; + graphics::draw(ctx, &node, (na::Point2::new(0.0, 0.0),))?; + } + + let fruit = graphics::Mesh::new_rectangle( + ctx, + graphics::DrawMode::fill(), + graphics::Rect { + x: self.fruit.0 as f32 * 10.0, + y: self.fruit.1 as f32 * 10.0, + h: 10.0, + w: 10.0, + }, + graphics::BLACK, + )?; + graphics::draw(ctx, &fruit, (na::Point2::new(0.0, 0.0),))?; + + graphics::present(ctx)?; + Ok(()) + } +}