Initial commit
commit
7d88220960
|
@ -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
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
[package]
|
||||
name = "afusnakec"
|
||||
version = "0.1.0"
|
||||
authors = ["kirbylife <kirbylife@protonmail.com>"]
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
ggez = "0.5"
|
||||
rand = "0.7.3"
|
|
@ -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<MainState> {
|
||||
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(())
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue