Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ edition = "2021"

[dependencies]
bevy = { version = "0.7.0", features = ["dynamic"] }
rand = "0.8.5"

# Enable a small amount of optimization in debug mode
[profile.dev]
Expand Down
25 changes: 25 additions & 0 deletions src/apple.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
use bevy::prelude::*;
use bevy::core::FixedTimestep;

use crate::board::Board;

pub struct Plugin;

impl bevy::prelude::Plugin for Plugin {
fn build(&self, app: &mut App) {
app.add_system_set(
SystemSet::new()
.with_run_criteria(FixedTimestep::step(5.0))
.with_system(add_apple)
);
}
}

#[derive(Component)]
pub struct Apple;

fn add_apple(mut commands: Commands, mut board: ResMut<Board>) {
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the major design decision. How much game state/knowledge should be encapsulated in Board vs. the ECS?

let loc = board.spawn_apple();
info!("spawning apple: {:?}", &loc);
commands.spawn().insert(Apple).insert(loc);
}
54 changes: 45 additions & 9 deletions src/board.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
use bevy::prelude::*;
use bevy::math::*;
use crate::App;
use crate::location::Location;
use bevy::prelude::*;
use std::collections::HashSet;

use rand::prelude::*;

use crate::direction::Direction;
use crate::location::Location;
use crate::App;

pub struct Plugin;

Expand All @@ -14,30 +18,62 @@ impl bevy::prelude::Plugin for Plugin {

pub(crate) struct Board {
pub(crate) limit: UVec2,
taken: HashSet<UVec2>,
}

impl Board {
pub fn adjacent(&self, loc: &Location, dir: &Direction) -> Option<Location> {
let coord = loc.coord;

let result_coord = match dir {
Direction::Up if coord.y < self.limit.y => uvec2(coord.x, coord.y + 1),
Direction::Down if coord.y > 0 => uvec2(coord.x, coord.y - 1),
Direction::Left if coord.x > 0 => uvec2(coord.x - 1, coord.y),
Direction::Up if coord.y < self.limit.y => uvec2(coord.x, coord.y + 1),
Direction::Down if coord.y > 0 => uvec2(coord.x, coord.y - 1),
Direction::Left if coord.x > 0 => uvec2(coord.x - 1, coord.y),
Direction::Right if coord.x < self.limit.x => uvec2(coord.x + 1, coord.y),
_ => return None,
};

Some(Location::new(result_coord))
}

pub fn starting_location(&self) -> Location {
Location::new(uvec2(self.limit.x / 2, (self.limit.y - 1) / 2 + 1))
pub fn reset(&mut self) -> Location {
self.taken.clear();
let coord = uvec2(self.limit.x / 2, (self.limit.y - 1) / 2 + 1);
self.taken.insert(coord);
Location::new(coord)
}

pub fn spawn_apple(&mut self) -> Location {
let x_range = 0..=self.limit.x;
let y_range = 0..=self.limit.y;
let mut rng = thread_rng();
loop {
let coord = uvec2(
rng.gen_range(x_range.clone()),
rng.gen_range(y_range.clone()),
);
if !self.taken.contains(&coord) {
self.taken.insert(coord);
return Location::new(coord);
}
}
}

pub fn block(&mut self, loc: &Location) {
assert!(!self.taken.contains(&loc.coord));
self.taken.insert(loc.coord);
}

pub fn clear(&mut self, loc: &Location) {
self.taken.remove(&loc.coord);
}
}

impl Default for Board {
fn default() -> Self {
Board { limit: uvec2(15, 8) }
Board {
limit: uvec2(15, 8),
taken: HashSet::new(),
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We'll eventually need to know what is at the location though.

}
}
}
4 changes: 2 additions & 2 deletions src/location.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use bevy::prelude::*;

#[derive(Component, Clone)]
#[derive(Component, Clone, Debug)]
pub struct Location {
pub coord: UVec2,
}
Expand All @@ -9,4 +9,4 @@ impl Location {
pub fn new(coord: UVec2) -> Self {
Self { coord }
}
}
}
2 changes: 2 additions & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ mod board;
mod render;
mod input;
mod window;
mod apple;

use bevy::prelude::*;

Expand All @@ -16,5 +17,6 @@ fn main() {
.add_plugin(render::Plugin)
.add_plugin(input::Plugin)
.add_plugin(board::Plugin)
.add_plugin(apple::Plugin)
.run();
}
15 changes: 9 additions & 6 deletions src/snake.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,11 @@ impl bevy::prelude::Plugin for Plugin {
}
}

fn setup(mut commands: Commands, board: Res<Board>) {
fn setup(mut commands: Commands, mut board: ResMut<Board>) {
let starting_loc = board.reset();
commands.spawn()
.insert(Head)
.insert(board.starting_location())
.insert(starting_loc)
.insert(Moving::default());
}

Expand All @@ -33,17 +34,19 @@ pub struct Moving {
pub(crate) last_dir: Direction,
}

fn move_snakes(board: Res<Board>, mut query: Query<(&mut Location, &mut Moving), With<Head>>) {
fn move_snakes(mut board: ResMut<Board>, mut query: Query<(&mut Location, &mut Moving), With<Head>>) {
for (mut loc, mut moving) in query.iter_mut() {
*loc = match board.adjacent(&loc, &moving.dir) {
Some(loc) => {
Some(new_loc) => {
board.clear(&loc);
board.block(&new_loc);
moving.last_dir = moving.dir;
loc
new_loc
},
None => {
println!("Snake hit a wall!");
*moving = Moving::default();
board.starting_location()
board.reset()
},
};
}
Expand Down