Update Bevy to 0.10
This commit is contained in:
1521
Cargo.lock
generated
1521
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
18
Cargo.toml
18
Cargo.toml
@@ -3,20 +3,16 @@ name = "bevy-snake"
|
|||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
iyes_loopless = "0.9.1"
|
|
||||||
itertools = "0.10.5"
|
itertools = "0.10.5"
|
||||||
rand = "0.8.5"
|
rand = "0.8.5"
|
||||||
bevy_editor_pls = "0.2.0"
|
bevy_editor_pls = "0.3.0"
|
||||||
bevy_tweening = "0.6.0"
|
bevy_tweening = "0.7.0"
|
||||||
leafwing-input-manager = "0.8.0"
|
leafwing-input-manager = "0.9.0"
|
||||||
|
|
||||||
[dependencies.bevy]
|
[dependencies.bevy]
|
||||||
version = "0.9.1"
|
version = "0.10"
|
||||||
features = ["dynamic", "wayland"]
|
features = ["wayland"]
|
||||||
|
|
||||||
[profile.dev.package."*"]
|
|
||||||
opt-level = 3
|
|
||||||
|
|
||||||
|
# [profile.dev.package."*"]
|
||||||
|
# opt-level = 3
|
||||||
|
|||||||
@@ -1,2 +1,2 @@
|
|||||||
[toolchain]
|
# [toolchain]
|
||||||
channel = "nightly"
|
# channel = "nightly"
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ use bevy::{
|
|||||||
render::{
|
render::{
|
||||||
render_resource::{encase, AsBindGroup, OwnedBindingResource, ShaderRef, ShaderType},
|
render_resource::{encase, AsBindGroup, OwnedBindingResource, ShaderRef, ShaderType},
|
||||||
renderer::RenderQueue,
|
renderer::RenderQueue,
|
||||||
RenderApp, RenderStage,
|
RenderApp, RenderSet,
|
||||||
},
|
},
|
||||||
sprite::{Material2d, Material2dPlugin, MaterialMesh2dBundle, RenderMaterials2d},
|
sprite::{Material2d, Material2dPlugin, MaterialMesh2dBundle, RenderMaterials2d},
|
||||||
};
|
};
|
||||||
@@ -23,8 +23,8 @@ impl Plugin for CanvasPlugin {
|
|||||||
.add_startup_system(spawn_canvas);
|
.add_startup_system(spawn_canvas);
|
||||||
|
|
||||||
app.sub_app_mut(RenderApp)
|
app.sub_app_mut(RenderApp)
|
||||||
.add_system_to_stage(RenderStage::Extract, extract_tile_lights)
|
.add_system(extract_tile_lights.in_schedule(ExtractSchedule))
|
||||||
.add_system_to_stage(RenderStage::Prepare, prepare_canvas_material);
|
.add_system(prepare_canvas_material.in_set(RenderSet::Prepare));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
grid,
|
grid,
|
||||||
snake::{self, SnakeHead},
|
snake::{self, SnakeHead},
|
||||||
tick,
|
|
||||||
};
|
};
|
||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
use iyes_loopless::prelude::*;
|
|
||||||
use rand::prelude::*;
|
use rand::prelude::*;
|
||||||
|
|
||||||
const Z_HEIGHT: f32 = snake::Z_HEIGHT / 2.;
|
const Z_HEIGHT: f32 = snake::Z_HEIGHT / 2.;
|
||||||
@@ -15,7 +13,7 @@ impl Plugin for FruitPlugin {
|
|||||||
fn build(&self, app: &mut App) {
|
fn build(&self, app: &mut App) {
|
||||||
app.add_event::<EatenEvent>()
|
app.add_event::<EatenEvent>()
|
||||||
.add_startup_system(spawn_fruit_system)
|
.add_startup_system(spawn_fruit_system)
|
||||||
.add_fixed_timestep_system(tick::TICK_TIME_STEP_NAME, 0, eat_fruit_system)
|
.add_system(eat_fruit_system.in_schedule(CoreSchedule::FixedUpdate))
|
||||||
.add_system(despawn_fruit_system)
|
.add_system(despawn_fruit_system)
|
||||||
.add_system(spawn_fruit_system.run_if(eaten_event_sent));
|
.add_system(spawn_fruit_system.run_if(eaten_event_sent));
|
||||||
}
|
}
|
||||||
|
|||||||
59
src/main.rs
59
src/main.rs
@@ -1,8 +1,12 @@
|
|||||||
use crate::{canvas::CanvasPlugin, fruit::FruitPlugin, snake::SnakePlugin, tick::TickPlugin};
|
use crate::{
|
||||||
use bevy::{prelude::*, render::camera::ScalingMode};
|
canvas::CanvasPlugin,
|
||||||
|
fruit::FruitPlugin,
|
||||||
|
grid::{SEGMENT_SIZE, SIZE},
|
||||||
|
snake::SnakePlugin,
|
||||||
|
};
|
||||||
|
use bevy::{prelude::*, render::camera::ScalingMode, window::WindowResolution};
|
||||||
use bevy_tweening::TweeningPlugin;
|
use bevy_tweening::TweeningPlugin;
|
||||||
use grid::{SEGMENT_SIZE, SIZE};
|
use std::time::Duration;
|
||||||
use iyes_loopless::prelude::*;
|
|
||||||
|
|
||||||
#[cfg(debug_assertions)]
|
#[cfg(debug_assertions)]
|
||||||
use bevy_editor_pls::prelude::*;
|
use bevy_editor_pls::prelude::*;
|
||||||
@@ -11,14 +15,16 @@ mod canvas;
|
|||||||
mod fruit;
|
mod fruit;
|
||||||
mod grid;
|
mod grid;
|
||||||
mod snake;
|
mod snake;
|
||||||
mod tick;
|
|
||||||
|
|
||||||
const ASPECT_RATIO: f32 = 16. / 9.;
|
const ASPECT_RATIO: f32 = 16. / 9.;
|
||||||
const WINDOW_WIDTH: f32 = 720. * ASPECT_RATIO;
|
const WINDOW_WIDTH: f32 = WINDOW_HEIGHT * ASPECT_RATIO;
|
||||||
const WINDOW_HEIGHT: f32 = 720.;
|
const WINDOW_HEIGHT: f32 = 720.;
|
||||||
|
const TICK_PERIOD: Duration = Duration::from_millis(125);
|
||||||
|
const CLEAR_COLOR: Color = Color::rgba(0.15, 0.15, 0.15, 1.0);
|
||||||
|
|
||||||
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
|
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, Default, States)]
|
||||||
enum AppState {
|
enum GameState {
|
||||||
|
#[default]
|
||||||
Begin,
|
Begin,
|
||||||
InGame,
|
InGame,
|
||||||
Paused,
|
Paused,
|
||||||
@@ -28,30 +34,31 @@ enum AppState {
|
|||||||
fn main() {
|
fn main() {
|
||||||
let mut app = App::new();
|
let mut app = App::new();
|
||||||
|
|
||||||
app.insert_resource(ClearColor(Color::rgb_u8(12, 12, 12)))
|
app.insert_resource(ClearColor(CLEAR_COLOR))
|
||||||
.add_loopless_state(AppState::Begin)
|
.insert_resource(FixedTime::new(TICK_PERIOD))
|
||||||
.add_plugins(DefaultPlugins.set(WindowPlugin {
|
.add_plugins(DefaultPlugins.set(WindowPlugin {
|
||||||
window: WindowDescriptor {
|
primary_window: Some(Window {
|
||||||
title: "Bevy-Snake".into(),
|
title: "Bevy-Snake".into(),
|
||||||
resizable: true,
|
resizable: true,
|
||||||
width: WINDOW_WIDTH,
|
resolution: WindowResolution::new(WINDOW_WIDTH, WINDOW_HEIGHT),
|
||||||
height: WINDOW_HEIGHT,
|
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
}),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}))
|
}))
|
||||||
|
.add_state::<GameState>()
|
||||||
.add_plugin(TweeningPlugin)
|
.add_plugin(TweeningPlugin)
|
||||||
.add_plugin(TickPlugin)
|
|
||||||
.add_plugin(SnakePlugin)
|
.add_plugin(SnakePlugin)
|
||||||
.add_plugin(FruitPlugin)
|
.add_plugin(FruitPlugin)
|
||||||
.add_plugin(CanvasPlugin)
|
.add_plugin(CanvasPlugin)
|
||||||
.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(pause_system);
|
|
||||||
|
|
||||||
#[cfg(debug_assertions)]
|
#[cfg(debug_assertions)]
|
||||||
app.add_plugin(EditorPlugin);
|
{
|
||||||
|
app.add_plugin(EditorPlugin)
|
||||||
|
.add_system(bevy::window::close_on_esc)
|
||||||
|
.add_system(pause_system);
|
||||||
|
}
|
||||||
|
|
||||||
app.run();
|
app.run();
|
||||||
}
|
}
|
||||||
@@ -62,7 +69,7 @@ fn setup_system(mut commands: Commands) {
|
|||||||
commands
|
commands
|
||||||
.spawn(Camera2dBundle {
|
.spawn(Camera2dBundle {
|
||||||
projection: OrthographicProjection {
|
projection: OrthographicProjection {
|
||||||
scaling_mode: ScalingMode::Auto {
|
scaling_mode: ScalingMode::AutoMin {
|
||||||
min_width: grid_dimensions,
|
min_width: grid_dimensions,
|
||||||
min_height: grid_dimensions,
|
min_height: grid_dimensions,
|
||||||
},
|
},
|
||||||
@@ -110,17 +117,17 @@ fn camera_move_system(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn pause_system(
|
fn pause_system(
|
||||||
mut commands: Commands,
|
|
||||||
keypress: Res<Input<KeyCode>>,
|
keypress: Res<Input<KeyCode>>,
|
||||||
state: Res<CurrentState<AppState>>,
|
current_state: Res<State<GameState>>,
|
||||||
|
mut next_state: ResMut<NextState<GameState>>,
|
||||||
) {
|
) {
|
||||||
if keypress.just_pressed(KeyCode::P) {
|
if keypress.just_pressed(KeyCode::P) {
|
||||||
let next_state = match state.0 {
|
let state = match current_state.0 {
|
||||||
AppState::InGame => AppState::Paused,
|
GameState::InGame => GameState::Paused,
|
||||||
AppState::Paused => AppState::InGame,
|
GameState::Paused => GameState::InGame,
|
||||||
_ => return,
|
_ => return,
|
||||||
};
|
};
|
||||||
|
|
||||||
commands.insert_resource(NextState(next_state));
|
next_state.set(state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
79
src/snake.rs
79
src/snake.rs
@@ -3,53 +3,65 @@ mod bulge;
|
|||||||
mod direction;
|
mod direction;
|
||||||
mod movement;
|
mod movement;
|
||||||
|
|
||||||
use crate::{fruit, grid, tick, AppState};
|
use crate::{fruit, grid, GameState};
|
||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
use direction::Direction;
|
use direction::Direction;
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use iyes_loopless::prelude::*;
|
|
||||||
use leafwing_input_manager::prelude::*;
|
use leafwing_input_manager::prelude::*;
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Hash, SystemLabel)]
|
#[derive(SystemSet, Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
enum SystemLabel {
|
enum SystemSet {
|
||||||
Collision,
|
Movement,
|
||||||
|
DirectionFlush,
|
||||||
|
CollisionDetection,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct SnakePlugin;
|
pub struct SnakePlugin;
|
||||||
|
|
||||||
impl Plugin for SnakePlugin {
|
impl Plugin for SnakePlugin {
|
||||||
fn build(&self, app: &mut App) {
|
fn build(&self, app: &mut App) {
|
||||||
let movement_system_set =
|
app.configure_set(SystemSet::Movement.after(SystemSet::CollisionDetection));
|
||||||
SystemSet::new().with_system(segments_movement_system.run_in_state(AppState::InGame));
|
|
||||||
|
|
||||||
let ticked_system_set = SystemSet::new()
|
|
||||||
.with_system(direction::apply_direction_system.run_in_state(AppState::InGame));
|
|
||||||
|
|
||||||
let collision_system_set = SystemSet::new()
|
|
||||||
.with_system(
|
|
||||||
game_over_system
|
|
||||||
.run_in_state(AppState::InGame)
|
|
||||||
.after(SystemLabel::Collision),
|
|
||||||
)
|
|
||||||
.with_system(
|
|
||||||
collision_system
|
|
||||||
.run_in_state(AppState::InGame)
|
|
||||||
.label(SystemLabel::Collision),
|
|
||||||
);
|
|
||||||
|
|
||||||
app.add_fixed_timestep_system_set(tick::TICK_TIME_STEP_NAME, 0, ticked_system_set)
|
|
||||||
.add_fixed_timestep_child_stage(tick::TICK_TIME_STEP_NAME)
|
|
||||||
.add_fixed_timestep_system_set(tick::TICK_TIME_STEP_NAME, 1, collision_system_set)
|
|
||||||
.add_fixed_timestep_child_stage(tick::TICK_TIME_STEP_NAME)
|
|
||||||
.add_fixed_timestep_system_set(tick::TICK_TIME_STEP_NAME, 2, movement_system_set);
|
|
||||||
|
|
||||||
app.add_plugin(InputManagerPlugin::<direction::Direction>::default())
|
app.add_plugin(InputManagerPlugin::<direction::Direction>::default())
|
||||||
.add_event::<AddTailEvent>()
|
.add_event::<AddTailEvent>()
|
||||||
.insert_resource(bulge::PropagationTimer::default())
|
.insert_resource(bulge::PropagationTimer::default())
|
||||||
.add_startup_system(setup_snake_system)
|
.add_startup_system(setup_snake_system)
|
||||||
.add_system(direction::start_game_system.run_in_state(AppState::Begin))
|
.add_system(
|
||||||
|
segments_movement_system
|
||||||
|
.in_schedule(CoreSchedule::FixedUpdate)
|
||||||
|
.in_set(SystemSet::Movement)
|
||||||
|
.run_if(in_state(GameState::InGame))
|
||||||
|
.after(SystemSet::DirectionFlush),
|
||||||
|
)
|
||||||
|
.add_system(
|
||||||
|
direction::apply_direction_system
|
||||||
|
.in_schedule(CoreSchedule::FixedUpdate)
|
||||||
|
.run_if(in_state(GameState::InGame))
|
||||||
|
.before(SystemSet::DirectionFlush),
|
||||||
|
)
|
||||||
|
.add_system(
|
||||||
|
apply_system_buffers
|
||||||
|
.in_schedule(CoreSchedule::FixedUpdate)
|
||||||
|
.in_set(SystemSet::DirectionFlush)
|
||||||
|
.run_if(in_state(GameState::InGame)),
|
||||||
|
)
|
||||||
|
.add_system(
|
||||||
|
collision_system
|
||||||
|
.in_schedule(CoreSchedule::FixedUpdate)
|
||||||
|
.in_set(SystemSet::CollisionDetection)
|
||||||
|
.run_if(in_state(GameState::InGame))
|
||||||
|
.after(SystemSet::DirectionFlush),
|
||||||
|
)
|
||||||
|
.add_system(
|
||||||
|
game_over_system
|
||||||
|
.in_schedule(CoreSchedule::FixedUpdate)
|
||||||
|
.in_set(SystemSet::CollisionDetection)
|
||||||
|
.in_set(OnUpdate(GameState::InGame))
|
||||||
|
.after(collision_system),
|
||||||
|
)
|
||||||
|
.add_system(direction::start_game_system.in_set(OnUpdate(GameState::Begin)))
|
||||||
.add_system(direction::change_direction_system)
|
.add_system(direction::change_direction_system)
|
||||||
.add_system(grid_transform_system.run_in_state(AppState::InGame))
|
.add_system(grid_transform_system.in_set(OnUpdate(GameState::InGame)))
|
||||||
.add_system(add_tail_system)
|
.add_system(add_tail_system)
|
||||||
.add_system(bulge::add_bulge_system)
|
.add_system(bulge::add_bulge_system)
|
||||||
.add_system(bulge::propagate_bulge_system)
|
.add_system(bulge::propagate_bulge_system)
|
||||||
@@ -220,9 +232,12 @@ fn collision_system(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn game_over_system(query: Query<&Collision, With<Snake>>, mut commands: Commands) {
|
fn game_over_system(
|
||||||
|
query: Query<&Collision, With<Snake>>,
|
||||||
|
mut next_state: ResMut<NextState<GameState>>,
|
||||||
|
) {
|
||||||
if query.get_single().unwrap().about_to_collide {
|
if query.get_single().unwrap().about_to_collide {
|
||||||
commands.insert_resource(NextState(AppState::End));
|
next_state.set(GameState::End);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
use super::{AddTailEvent, Segments, Snake, SnakeHead, SnakeSegment};
|
use super::{AddTailEvent, Segments, Snake, SnakeHead, SnakeSegment};
|
||||||
use crate::tick::TICK_PERIOD;
|
use crate::TICK_PERIOD;
|
||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
use bevy_tweening::{lens::TransformScaleLens, *};
|
use bevy_tweening::{lens::TransformScaleLens, *};
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
@@ -13,10 +13,7 @@ pub(super) struct PropagationTimer(Timer);
|
|||||||
|
|
||||||
impl Default for PropagationTimer {
|
impl Default for PropagationTimer {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self(Timer::new(
|
Self(Timer::new(TICK_PERIOD / 4, TimerMode::Repeating))
|
||||||
Duration::from_millis(TICK_PERIOD / 4),
|
|
||||||
TimerMode::Repeating,
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
61
src/snake/direction.rs
Normal file
61
src/snake/direction.rs
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
use super::Snake;
|
||||||
|
use crate::GameState;
|
||||||
|
use bevy::prelude::*;
|
||||||
|
use leafwing_input_manager::prelude::*;
|
||||||
|
|
||||||
|
#[derive(Actionlike, Component, Copy, Clone, Debug)]
|
||||||
|
pub(super) enum Direction {
|
||||||
|
Up,
|
||||||
|
Down,
|
||||||
|
Left,
|
||||||
|
Right,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Component, Copy, Clone, Debug)]
|
||||||
|
#[component(storage = "SparseSet")]
|
||||||
|
pub(super) struct NewDirection(Direction);
|
||||||
|
|
||||||
|
pub(super) fn start_game_system(
|
||||||
|
query: Query<&ActionState<Direction>>,
|
||||||
|
mut next_state: ResMut<NextState<GameState>>,
|
||||||
|
) {
|
||||||
|
let action_state = query.single();
|
||||||
|
|
||||||
|
if !action_state.get_just_pressed().is_empty() {
|
||||||
|
next_state.set(GameState::InGame);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super) fn apply_direction_system(
|
||||||
|
mut commands: Commands,
|
||||||
|
mut query: Query<(Entity, &NewDirection), With<Snake>>,
|
||||||
|
) {
|
||||||
|
for (snake, new_direction) in query.iter_mut() {
|
||||||
|
commands
|
||||||
|
.entity(snake)
|
||||||
|
.insert(new_direction.0)
|
||||||
|
.remove::<NewDirection>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super) fn change_direction_system(
|
||||||
|
mut commands: Commands,
|
||||||
|
mut query: Query<(Entity, &ActionState<Direction>, Option<&Direction>), With<Snake>>,
|
||||||
|
) {
|
||||||
|
let (snake, action_state, direction) = query.single_mut();
|
||||||
|
let new_direction = action_state.get_pressed().iter().cloned().last();
|
||||||
|
|
||||||
|
if let Some(new_direction) = new_direction {
|
||||||
|
if let Some(current_direction) = direction {
|
||||||
|
if let (Direction::Up, Direction::Down)
|
||||||
|
| (Direction::Down, Direction::Up)
|
||||||
|
| (Direction::Left, Direction::Right)
|
||||||
|
| (Direction::Right, Direction::Left) = (current_direction, new_direction)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
commands.entity(snake).insert(NewDirection(new_direction));
|
||||||
|
}
|
||||||
|
}
|
||||||
14
src/tick.rs
14
src/tick.rs
@@ -1,14 +0,0 @@
|
|||||||
use bevy::prelude::*;
|
|
||||||
use iyes_loopless::prelude::*;
|
|
||||||
use std::time::Duration;
|
|
||||||
|
|
||||||
pub const TICK_PERIOD: u64 = 125;
|
|
||||||
pub const TICK_TIME_STEP_NAME: &str = "tick_time_step";
|
|
||||||
|
|
||||||
pub struct TickPlugin;
|
|
||||||
|
|
||||||
impl Plugin for TickPlugin {
|
|
||||||
fn build(&self, app: &mut App) {
|
|
||||||
app.add_fixed_timestep(Duration::from_millis(TICK_PERIOD), TICK_TIME_STEP_NAME);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user