Update Bevy to 0.10

This commit is contained in:
2023-03-12 20:34:23 +01:00
parent 326e75e40a
commit 3724db44b3
10 changed files with 853 additions and 920 deletions

1521
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -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

View File

@@ -1,2 +1,2 @@
[toolchain] # [toolchain]
channel = "nightly" # channel = "nightly"

View File

@@ -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));
} }
} }

View File

@@ -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));
} }

View File

@@ -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);
} }
} }

View File

@@ -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);
} }
} }

View File

@@ -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
View 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));
}
}

View File

@@ -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);
}
}