Game over system fix
This commit is contained in:
21
src/canvas.rs
Normal file
21
src/canvas.rs
Normal file
@@ -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()
|
||||||
|
});
|
||||||
|
}
|
||||||
51
src/grid.rs
51
src/grid.rs
@@ -1,65 +1,46 @@
|
|||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
use std::ops::{Add, AddAssign};
|
use std::ops::{Add, AddAssign};
|
||||||
|
|
||||||
pub type GridType = i16;
|
pub type Index = i16;
|
||||||
|
|
||||||
pub const GRID_SIZE: GridType = 21;
|
pub const SIZE: Index = 17;
|
||||||
pub const GRID_SEGMENT_SIZE: f32 = 20.;
|
pub const SEGMENT_SIZE: f32 = 20.;
|
||||||
|
|
||||||
#[derive(Component, Clone, Copy, Default, Debug)]
|
#[derive(Component, Clone, Copy, Default, Debug)]
|
||||||
pub struct GridCoordinate(pub GridType, pub GridType);
|
pub struct Coordinate(pub Index, pub Index);
|
||||||
|
|
||||||
impl GridCoordinate {
|
impl Coordinate {
|
||||||
pub fn splat(v: GridType) -> Self {
|
pub fn splat(v: Index) -> Self {
|
||||||
Self(v, v)
|
Self(v, v)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Add for GridCoordinate {
|
impl Add for Coordinate {
|
||||||
type Output = Self;
|
type Output = Self;
|
||||||
|
|
||||||
fn add(self, rhs: GridCoordinate) -> Self::Output {
|
fn add(self, rhs: Coordinate) -> Self::Output {
|
||||||
GridCoordinate(self.0 + rhs.0, self.1 + rhs.1)
|
Coordinate(self.0 + rhs.0, self.1 + rhs.1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AddAssign for GridCoordinate {
|
impl AddAssign for Coordinate {
|
||||||
fn add_assign(&mut self, rhs: Self) {
|
fn add_assign(&mut self, rhs: Self) {
|
||||||
*self = Self(self.0 + rhs.0, self.1 + rhs.1)
|
*self = Self(self.0 + rhs.0, self.1 + rhs.1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<GridCoordinate> for Transform {
|
impl From<Coordinate> for Transform {
|
||||||
fn from(grid_coordinate: GridCoordinate) -> Self {
|
fn from(grid_coordinate: Coordinate) -> Self {
|
||||||
(&grid_coordinate).into()
|
(&grid_coordinate).into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<&GridCoordinate> for Transform {
|
impl From<&Coordinate> for Transform {
|
||||||
fn from(grid_coordinate: &GridCoordinate) -> Self {
|
fn from(grid_coordinate: &Coordinate) -> Self {
|
||||||
Transform::from_xyz(
|
Transform::from_xyz(
|
||||||
(grid_coordinate.0 - GRID_SIZE / 2) as f32 * GRID_SEGMENT_SIZE,
|
(grid_coordinate.0 - SIZE / 2) as f32 * SEGMENT_SIZE,
|
||||||
(grid_coordinate.1 - GRID_SIZE / 2) as f32 * GRID_SEGMENT_SIZE,
|
(grid_coordinate.1 - SIZE / 2) as f32 * SEGMENT_SIZE,
|
||||||
0.,
|
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()
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
use bevy::{prelude::*, render::camera::ScalingMode};
|
use bevy::{prelude::*, render::camera::ScalingMode};
|
||||||
// use bevy_editor_pls::prelude::*;
|
// use bevy_editor_pls::prelude::*;
|
||||||
use grid::{GRID_SEGMENT_SIZE, GRID_SIZE};
|
use grid::{SEGMENT_SIZE, SIZE};
|
||||||
use iyes_loopless::prelude::*;
|
use iyes_loopless::prelude::*;
|
||||||
|
|
||||||
|
mod canvas;
|
||||||
mod grid;
|
mod grid;
|
||||||
mod snake;
|
mod snake;
|
||||||
|
|
||||||
@@ -31,8 +32,8 @@ fn main() {
|
|||||||
.add_loopless_state(AppState::Begin)
|
.add_loopless_state(AppState::Begin)
|
||||||
.add_plugins(DefaultPlugins)
|
.add_plugins(DefaultPlugins)
|
||||||
// .add_plugin(EditorPlugin)
|
// .add_plugin(EditorPlugin)
|
||||||
.add_plugin(snake::SnakePlugin)
|
.add_plugin(snake::ModPlugin)
|
||||||
.add_plugin(grid::GridPlugin)
|
.add_plugin(canvas::ModPlugin)
|
||||||
.add_startup_system(setup_system)
|
.add_startup_system(setup_system)
|
||||||
.add_system(camera_move_system)
|
.add_system(camera_move_system)
|
||||||
.add_system(bevy::window::close_on_esc)
|
.add_system(bevy::window::close_on_esc)
|
||||||
@@ -41,7 +42,7 @@ fn main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn setup_system(mut commands: Commands) {
|
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
|
commands
|
||||||
.spawn_bundle(Camera2dBundle {
|
.spawn_bundle(Camera2dBundle {
|
||||||
|
|||||||
80
src/snake.rs
80
src/snake.rs
@@ -1,7 +1,4 @@
|
|||||||
use crate::{
|
use crate::{grid, AppState};
|
||||||
grid::{GridCoordinate, GridType, GRID_SEGMENT_SIZE, GRID_SIZE},
|
|
||||||
AppState,
|
|
||||||
};
|
|
||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use iyes_loopless::prelude::*;
|
use iyes_loopless::prelude::*;
|
||||||
@@ -10,27 +7,36 @@ use std::time::Duration;
|
|||||||
#[derive(Debug, Clone, PartialEq, Eq, Hash, StageLabel)]
|
#[derive(Debug, Clone, PartialEq, Eq, Hash, StageLabel)]
|
||||||
struct FixedTimeStage;
|
struct FixedTimeStage;
|
||||||
|
|
||||||
pub struct SnakePlugin;
|
pub struct ModPlugin;
|
||||||
|
|
||||||
impl Plugin for SnakePlugin {
|
impl Plugin for ModPlugin {
|
||||||
fn build(&self, app: &mut App) {
|
fn build(&self, app: &mut App) {
|
||||||
let mut fixed_time_systems0 = SystemStage::parallel();
|
let mut fixed_time_systems0 = SystemStage::parallel();
|
||||||
fixed_time_systems0.add_system(segments_movement_system.run_in_state(AppState::InGame));
|
fixed_time_systems0.add_system(segments_movement_system.run_in_state(AppState::InGame));
|
||||||
|
|
||||||
let mut fixed_time_systems1 = SystemStage::parallel();
|
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)
|
app.add_startup_system(setup_snake_system)
|
||||||
.add_stage_before(
|
.add_stage_before(
|
||||||
CoreStage::Update,
|
CoreStage::Update,
|
||||||
FixedTimeStage,
|
FixedTimeStage,
|
||||||
FixedTimestepStage::new(Duration::from_millis(100))
|
FixedTimestepStage::new(Duration::from_millis(125))
|
||||||
.with_stage(fixed_time_systems0)
|
.with_stage(fixed_time_systems0)
|
||||||
.with_stage(fixed_time_systems1),
|
.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(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(grid_transform_system.run_in_state(AppState::InGame))
|
||||||
.add_system(add_tail_system);
|
.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
|
commands
|
||||||
.spawn_bundle(SpriteBundle {
|
.spawn_bundle(SpriteBundle {
|
||||||
sprite: Sprite {
|
sprite: Sprite {
|
||||||
color: Color::RED,
|
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()
|
..Default::default()
|
||||||
},
|
},
|
||||||
transform: grid_position.into(),
|
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) {
|
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
|
commands
|
||||||
.entity(snake_head)
|
.entity(snake_head)
|
||||||
@@ -130,14 +136,15 @@ fn add_tail_system(
|
|||||||
mut snake_query: Query<(Entity, &mut SnakeSegments)>,
|
mut snake_query: Query<(Entity, &mut SnakeSegments)>,
|
||||||
) {
|
) {
|
||||||
if keypress.just_pressed(KeyCode::Space) {
|
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();
|
let (snake, mut snake_segments) = snake_query.single_mut();
|
||||||
snake_segments.0.push(segment);
|
snake_segments.0.push(segment);
|
||||||
commands.entity(snake).add_child(segment);
|
commands.entity(snake).add_child(segment);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn direction_system(
|
fn change_direction_system(
|
||||||
keypress: Res<Input<KeyCode>>,
|
keypress: Res<Input<KeyCode>>,
|
||||||
mut query: Query<&mut Direction, With<SnakeHead>>,
|
mut query: Query<&mut Direction, With<SnakeHead>>,
|
||||||
) {
|
) {
|
||||||
@@ -156,26 +163,28 @@ fn direction_system(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn grid_transform_system(mut query: Query<(&mut Transform, &GridCoordinate), With<SnakeSegment>>) {
|
fn grid_transform_system(
|
||||||
|
mut query: Query<(&mut Transform, &grid::Coordinate), With<SnakeSegment>>,
|
||||||
|
) {
|
||||||
for (mut transform, grid_coordinate) in query.iter_mut() {
|
for (mut transform, grid_coordinate) in query.iter_mut() {
|
||||||
*transform = grid_coordinate.into();
|
*transform = grid_coordinate.into();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn head_movement_system(mut query: Query<(&mut GridCoordinate, &Direction), With<SnakeHead>>) {
|
fn head_movement_system(mut query: Query<(&mut grid::Coordinate, &Direction), With<SnakeHead>>) {
|
||||||
let (mut grid_coordinate, direction) = query.single_mut();
|
let (mut grid_coordinate, direction) = query.single_mut();
|
||||||
|
|
||||||
match direction {
|
match direction {
|
||||||
Direction::Up => *grid_coordinate += GridCoordinate(0, 1),
|
Direction::Up => *grid_coordinate += grid::Coordinate(0, 1),
|
||||||
Direction::Down => *grid_coordinate += GridCoordinate(0, -1),
|
Direction::Down => *grid_coordinate += grid::Coordinate(0, -1),
|
||||||
Direction::Left => *grid_coordinate += GridCoordinate(-1, 0),
|
Direction::Left => *grid_coordinate += grid::Coordinate(-1, 0),
|
||||||
Direction::Right => *grid_coordinate += GridCoordinate(1, 0),
|
Direction::Right => *grid_coordinate += grid::Coordinate(1, 0),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn segments_movement_system(
|
fn segments_movement_system(
|
||||||
snake_segments_query: Query<&SnakeSegments>,
|
snake_segments_query: Query<&SnakeSegments>,
|
||||||
mut segment_query: Query<&mut GridCoordinate, With<SnakeSegment>>,
|
mut segment_query: Query<&mut grid::Coordinate, With<SnakeSegment>>,
|
||||||
) {
|
) {
|
||||||
for snake_segments in snake_segments_query.iter() {
|
for snake_segments in snake_segments_query.iter() {
|
||||||
for (&segment_entity, &previous_segment_entity) in
|
for (&segment_entity, &previous_segment_entity) in
|
||||||
@@ -188,19 +197,18 @@ fn segments_movement_system(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn game_over_system(
|
fn about_to_lose(query: Query<(&grid::Coordinate, &Direction), With<SnakeHead>>) -> bool {
|
||||||
mut commands: Commands,
|
const HIGH_BARRIER: grid::Index = grid::SIZE - 1;
|
||||||
query: Query<(&GridCoordinate, &Direction), With<SnakeHead>>,
|
|
||||||
) {
|
|
||||||
const HIGH_BARRIER: GridType = GRID_SIZE - 1;
|
|
||||||
|
|
||||||
match query.single() {
|
matches!(
|
||||||
(GridCoordinate(_, 0), Direction::Down)
|
query.single(),
|
||||||
| (GridCoordinate(_, HIGH_BARRIER), Direction::Up)
|
(grid::Coordinate(_, 0), Direction::Down)
|
||||||
| (GridCoordinate(0, _), Direction::Left)
|
| (grid::Coordinate(_, HIGH_BARRIER), Direction::Up)
|
||||||
| (GridCoordinate(HIGH_BARRIER, _), Direction::Right) => {
|
| (grid::Coordinate(0, _), Direction::Left)
|
||||||
commands.insert_resource(NextState(AppState::End))
|
| (grid::Coordinate(HIGH_BARRIER, _), Direction::Right)
|
||||||
}
|
)
|
||||||
_ => (),
|
}
|
||||||
};
|
|
||||||
|
fn game_over_system(mut commands: Commands) {
|
||||||
|
commands.insert_resource(NextState(AppState::End));
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user