diff --git a/src/canvas.rs b/src/canvas.rs new file mode 100644 index 0000000..646863e --- /dev/null +++ b/src/canvas.rs @@ -0,0 +1,21 @@ +use crate::grid; +use bevy::prelude::*; + +pub struct ModPlugin; + +impl Plugin for ModPlugin { + fn build(&self, app: &mut App) { + app.add_startup_system(spawn_background); + } +} + +fn spawn_background(mut commands: Commands) { + commands.spawn_bundle(SpriteBundle { + sprite: Sprite { + color: Color::DARK_GRAY, + custom_size: Some(Vec2::splat(grid::SEGMENT_SIZE * grid::SIZE as f32)), + ..Default::default() + }, + ..Default::default() + }); +} diff --git a/src/grid.rs b/src/grid.rs index 789943a..cd1d4e0 100644 --- a/src/grid.rs +++ b/src/grid.rs @@ -1,65 +1,46 @@ use bevy::prelude::*; use std::ops::{Add, AddAssign}; -pub type GridType = i16; +pub type Index = i16; -pub const GRID_SIZE: GridType = 21; -pub const GRID_SEGMENT_SIZE: f32 = 20.; +pub const SIZE: Index = 17; +pub const SEGMENT_SIZE: f32 = 20.; #[derive(Component, Clone, Copy, Default, Debug)] -pub struct GridCoordinate(pub GridType, pub GridType); +pub struct Coordinate(pub Index, pub Index); -impl GridCoordinate { - pub fn splat(v: GridType) -> Self { +impl Coordinate { + pub fn splat(v: Index) -> Self { Self(v, v) } } -impl Add for GridCoordinate { +impl Add for Coordinate { type Output = Self; - fn add(self, rhs: GridCoordinate) -> Self::Output { - GridCoordinate(self.0 + rhs.0, self.1 + rhs.1) + fn add(self, rhs: Coordinate) -> Self::Output { + Coordinate(self.0 + rhs.0, self.1 + rhs.1) } } -impl AddAssign for GridCoordinate { +impl AddAssign for Coordinate { fn add_assign(&mut self, rhs: Self) { *self = Self(self.0 + rhs.0, self.1 + rhs.1) } } -impl From for Transform { - fn from(grid_coordinate: GridCoordinate) -> Self { +impl From for Transform { + fn from(grid_coordinate: Coordinate) -> Self { (&grid_coordinate).into() } } -impl From<&GridCoordinate> for Transform { - fn from(grid_coordinate: &GridCoordinate) -> Self { +impl From<&Coordinate> for Transform { + fn from(grid_coordinate: &Coordinate) -> Self { Transform::from_xyz( - (grid_coordinate.0 - GRID_SIZE / 2) as f32 * GRID_SEGMENT_SIZE, - (grid_coordinate.1 - GRID_SIZE / 2) as f32 * GRID_SEGMENT_SIZE, + (grid_coordinate.0 - SIZE / 2) as f32 * SEGMENT_SIZE, + (grid_coordinate.1 - SIZE / 2) as f32 * SEGMENT_SIZE, 0., ) } } - -pub struct GridPlugin; - -impl Plugin for GridPlugin { - fn build(&self, app: &mut App) { - app.add_startup_system(spawn_background); - } -} - -fn spawn_background(mut commands: Commands) { - commands.spawn_bundle(SpriteBundle { - sprite: Sprite { - color: Color::DARK_GRAY, - custom_size: Some(Vec2::splat(GRID_SEGMENT_SIZE * GRID_SIZE as f32)), - ..Default::default() - }, - ..Default::default() - }); -} diff --git a/src/main.rs b/src/main.rs index d0d036a..98ff5c0 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,8 +1,9 @@ use bevy::{prelude::*, render::camera::ScalingMode}; // use bevy_editor_pls::prelude::*; -use grid::{GRID_SEGMENT_SIZE, GRID_SIZE}; +use grid::{SEGMENT_SIZE, SIZE}; use iyes_loopless::prelude::*; +mod canvas; mod grid; mod snake; @@ -31,8 +32,8 @@ fn main() { .add_loopless_state(AppState::Begin) .add_plugins(DefaultPlugins) // .add_plugin(EditorPlugin) - .add_plugin(snake::SnakePlugin) - .add_plugin(grid::GridPlugin) + .add_plugin(snake::ModPlugin) + .add_plugin(canvas::ModPlugin) .add_startup_system(setup_system) .add_system(camera_move_system) .add_system(bevy::window::close_on_esc) @@ -41,7 +42,7 @@ fn main() { } fn setup_system(mut commands: Commands) { - let grid_dimensions = GRID_SIZE as f32 * GRID_SEGMENT_SIZE * 1.2; + let grid_dimensions = SIZE as f32 * SEGMENT_SIZE * 1.2; commands .spawn_bundle(Camera2dBundle { diff --git a/src/snake.rs b/src/snake.rs index 407cf88..b898b2c 100644 --- a/src/snake.rs +++ b/src/snake.rs @@ -1,7 +1,4 @@ -use crate::{ - grid::{GridCoordinate, GridType, GRID_SEGMENT_SIZE, GRID_SIZE}, - AppState, -}; +use crate::{grid, AppState}; use bevy::prelude::*; use itertools::Itertools; use iyes_loopless::prelude::*; @@ -10,27 +7,36 @@ use std::time::Duration; #[derive(Debug, Clone, PartialEq, Eq, Hash, StageLabel)] struct FixedTimeStage; -pub struct SnakePlugin; +pub struct ModPlugin; -impl Plugin for SnakePlugin { +impl Plugin for ModPlugin { fn build(&self, app: &mut App) { let mut fixed_time_systems0 = SystemStage::parallel(); fixed_time_systems0.add_system(segments_movement_system.run_in_state(AppState::InGame)); let mut fixed_time_systems1 = SystemStage::parallel(); - fixed_time_systems1.add_system(head_movement_system.run_in_state(AppState::InGame)); + fixed_time_systems1 + .add_system( + head_movement_system + .run_in_state(AppState::InGame) + .run_if_not(about_to_lose), + ) + .add_system( + game_over_system + .run_in_state(AppState::InGame) + .run_if(about_to_lose), + ); app.add_startup_system(setup_snake_system) .add_stage_before( CoreStage::Update, FixedTimeStage, - FixedTimestepStage::new(Duration::from_millis(100)) + FixedTimestepStage::new(Duration::from_millis(125)) .with_stage(fixed_time_systems0) .with_stage(fixed_time_systems1), ) - .add_system(game_over_system.run_in_state(AppState::InGame)) .add_system(add_direction_system.run_in_state(AppState::Begin)) - .add_system(direction_system.run_in_state(AppState::InGame)) + .add_system(change_direction_system.run_in_state(AppState::InGame)) .add_system(grid_transform_system.run_in_state(AppState::InGame)) .add_system(add_tail_system); } @@ -78,12 +84,12 @@ impl Direction { } } -fn create_snake_segment(commands: &mut Commands, grid_position: GridCoordinate) -> Entity { +fn create_snake_segment(commands: &mut Commands, grid_position: grid::Coordinate) -> Entity { commands .spawn_bundle(SpriteBundle { sprite: Sprite { color: Color::RED, - custom_size: Some(Vec2::splat(GRID_SEGMENT_SIZE) * 0.9), + custom_size: Some(Vec2::splat(grid::SEGMENT_SIZE) * 0.9), ..Default::default() }, transform: grid_position.into(), @@ -95,7 +101,7 @@ fn create_snake_segment(commands: &mut Commands, grid_position: GridCoordinate) } fn setup_snake_system(mut commands: Commands) { - let snake_head = create_snake_segment(&mut commands, GridCoordinate::splat(GRID_SIZE / 2)); + let snake_head = create_snake_segment(&mut commands, grid::Coordinate::splat(grid::SIZE / 2)); commands .entity(snake_head) @@ -130,14 +136,15 @@ fn add_tail_system( mut snake_query: Query<(Entity, &mut SnakeSegments)>, ) { if keypress.just_pressed(KeyCode::Space) { - let segment = create_snake_segment(&mut commands, GridCoordinate::splat(GridType::MIN / 2)); + let segment = + create_snake_segment(&mut commands, grid::Coordinate::splat(grid::Index::MIN / 2)); let (snake, mut snake_segments) = snake_query.single_mut(); snake_segments.0.push(segment); commands.entity(snake).add_child(segment); } } -fn direction_system( +fn change_direction_system( keypress: Res>, mut query: Query<&mut Direction, With>, ) { @@ -156,26 +163,28 @@ fn direction_system( } } -fn grid_transform_system(mut query: Query<(&mut Transform, &GridCoordinate), With>) { +fn grid_transform_system( + mut query: Query<(&mut Transform, &grid::Coordinate), With>, +) { for (mut transform, grid_coordinate) in query.iter_mut() { *transform = grid_coordinate.into(); } } -fn head_movement_system(mut query: Query<(&mut GridCoordinate, &Direction), With>) { +fn head_movement_system(mut query: Query<(&mut grid::Coordinate, &Direction), With>) { let (mut grid_coordinate, direction) = query.single_mut(); match direction { - Direction::Up => *grid_coordinate += GridCoordinate(0, 1), - Direction::Down => *grid_coordinate += GridCoordinate(0, -1), - Direction::Left => *grid_coordinate += GridCoordinate(-1, 0), - Direction::Right => *grid_coordinate += GridCoordinate(1, 0), + Direction::Up => *grid_coordinate += grid::Coordinate(0, 1), + Direction::Down => *grid_coordinate += grid::Coordinate(0, -1), + Direction::Left => *grid_coordinate += grid::Coordinate(-1, 0), + Direction::Right => *grid_coordinate += grid::Coordinate(1, 0), }; } fn segments_movement_system( snake_segments_query: Query<&SnakeSegments>, - mut segment_query: Query<&mut GridCoordinate, With>, + mut segment_query: Query<&mut grid::Coordinate, With>, ) { for snake_segments in snake_segments_query.iter() { for (&segment_entity, &previous_segment_entity) in @@ -188,19 +197,18 @@ fn segments_movement_system( } } -fn game_over_system( - mut commands: Commands, - query: Query<(&GridCoordinate, &Direction), With>, -) { - const HIGH_BARRIER: GridType = GRID_SIZE - 1; +fn about_to_lose(query: Query<(&grid::Coordinate, &Direction), With>) -> bool { + const HIGH_BARRIER: grid::Index = grid::SIZE - 1; - match query.single() { - (GridCoordinate(_, 0), Direction::Down) - | (GridCoordinate(_, HIGH_BARRIER), Direction::Up) - | (GridCoordinate(0, _), Direction::Left) - | (GridCoordinate(HIGH_BARRIER, _), Direction::Right) => { - commands.insert_resource(NextState(AppState::End)) - } - _ => (), - }; + matches!( + query.single(), + (grid::Coordinate(_, 0), Direction::Down) + | (grid::Coordinate(_, HIGH_BARRIER), Direction::Up) + | (grid::Coordinate(0, _), Direction::Left) + | (grid::Coordinate(HIGH_BARRIER, _), Direction::Right) + ) +} + +fn game_over_system(mut commands: Commands) { + commands.insert_resource(NextState(AppState::End)); }