Update to Bevy 0.9
This commit is contained in:
1000
Cargo.lock
generated
1000
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@@ -6,14 +6,14 @@ edition = "2021"
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
iyes_loopless = "0.8.0"
|
||||
iyes_loopless = "0.9.1"
|
||||
itertools = "0.10.5"
|
||||
rand = "0.8.5"
|
||||
bevy_editor_pls = "0.1.1"
|
||||
bevy_tweening = "0.5.0"
|
||||
bevy_editor_pls = "0.2.0"
|
||||
bevy_tweening = "0.6.0"
|
||||
|
||||
[dependencies.bevy]
|
||||
version = "0.8.1"
|
||||
version = "0.9.0"
|
||||
features = ["dynamic"]
|
||||
|
||||
[profile.dev.package."*"]
|
||||
|
||||
@@ -11,7 +11,7 @@ impl Plugin for CanvasPlugin {
|
||||
|
||||
fn spawn_background(mut commands: Commands) {
|
||||
commands
|
||||
.spawn_bundle(SpriteBundle {
|
||||
.spawn(SpriteBundle {
|
||||
sprite: Sprite {
|
||||
color: Color::DARK_GRAY,
|
||||
custom_size: Some(Vec2::splat(grid::SEGMENT_SIZE * f32::from(grid::SIZE))),
|
||||
|
||||
@@ -14,7 +14,7 @@ pub struct FruitPlugin;
|
||||
impl Plugin for FruitPlugin {
|
||||
fn build(&self, app: &mut App) {
|
||||
app.add_event::<EatenEvent>()
|
||||
.add_startup_system(spawn_fruit_system.after(snake::SystemLabel::StartUp))
|
||||
.add_startup_system(spawn_fruit_system)
|
||||
.add_system(eat_fruit_system.run_if(tick_triggered))
|
||||
.add_system(debug_eaten_event_system)
|
||||
.add_system(despawn_fruit_system)
|
||||
@@ -53,7 +53,7 @@ fn spawn_fruit_system(mut commands: Commands, coordinate_query: Query<&grid::Coo
|
||||
.expect("Should always be found.");
|
||||
|
||||
commands
|
||||
.spawn_bundle(SpriteBundle {
|
||||
.spawn(SpriteBundle {
|
||||
sprite: Sprite {
|
||||
color: Color::GREEN,
|
||||
custom_size: Some(Vec2::splat(grid::SEGMENT_SIZE) * 0.6),
|
||||
|
||||
20
src/main.rs
20
src/main.rs
@@ -26,15 +26,17 @@ enum AppState {
|
||||
fn main() {
|
||||
App::new()
|
||||
.insert_resource(ClearColor(Color::rgb_u8(12, 12, 12)))
|
||||
.insert_resource(WindowDescriptor {
|
||||
title: "Bevy-Snake".into(),
|
||||
resizable: true,
|
||||
width: WINDOW_WIDTH,
|
||||
height: WINDOW_HEIGHT,
|
||||
..Default::default()
|
||||
})
|
||||
.add_loopless_state(AppState::Begin)
|
||||
.add_plugins(DefaultPlugins)
|
||||
.add_plugins(DefaultPlugins.set(WindowPlugin {
|
||||
window: WindowDescriptor {
|
||||
title: "Bevy-Snake".into(),
|
||||
resizable: true,
|
||||
width: WINDOW_WIDTH,
|
||||
height: WINDOW_HEIGHT,
|
||||
..Default::default()
|
||||
},
|
||||
..Default::default()
|
||||
}))
|
||||
.add_plugin(EditorPlugin)
|
||||
.add_plugin(TweeningPlugin)
|
||||
.add_plugin(TickPlugin)
|
||||
@@ -52,7 +54,7 @@ fn setup_system(mut commands: Commands) {
|
||||
let grid_dimensions = f32::from(SIZE) * SEGMENT_SIZE * 1.2;
|
||||
|
||||
commands
|
||||
.spawn_bundle(Camera2dBundle {
|
||||
.spawn(Camera2dBundle {
|
||||
projection: OrthographicProjection {
|
||||
scaling_mode: ScalingMode::Auto {
|
||||
min_width: grid_dimensions,
|
||||
|
||||
86
src/snake.rs
86
src/snake.rs
@@ -13,12 +13,6 @@ use iyes_loopless::prelude::*;
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash, StageLabel)]
|
||||
struct MovementStage;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash, SystemLabel)]
|
||||
pub enum SystemLabel {
|
||||
StartUp,
|
||||
SegmentMovement,
|
||||
}
|
||||
|
||||
pub struct SnakePlugin;
|
||||
|
||||
impl Plugin for SnakePlugin {
|
||||
@@ -26,14 +20,13 @@ impl Plugin for SnakePlugin {
|
||||
let movement_stage = SystemStage::parallel();
|
||||
|
||||
app.insert_resource(BulgePropagationTimer::default())
|
||||
.add_startup_system(setup_snake_system.label(SystemLabel::StartUp))
|
||||
.add_startup_system(setup_snake_system)
|
||||
.add_stage_after(CoreStage::Update, MovementStage, movement_stage)
|
||||
.add_system_to_stage(
|
||||
MovementStage,
|
||||
segments_movement_system
|
||||
.run_in_state(AppState::InGame)
|
||||
.run_if(tick_triggered)
|
||||
.label(SystemLabel::SegmentMovement),
|
||||
.run_if(tick_triggered),
|
||||
)
|
||||
.add_system(
|
||||
apply_direction_system
|
||||
@@ -69,19 +62,13 @@ struct SnakeSegment;
|
||||
pub struct SnakeHead;
|
||||
|
||||
#[derive(Component, Debug)]
|
||||
struct Snake {
|
||||
about_to_collide: bool,
|
||||
segments: Vec<Entity>,
|
||||
}
|
||||
struct Segments(Vec<Entity>);
|
||||
|
||||
impl Snake {
|
||||
fn with_segments(segments: &[Entity]) -> Self {
|
||||
Self {
|
||||
about_to_collide: false,
|
||||
segments: segments.to_owned(),
|
||||
}
|
||||
}
|
||||
}
|
||||
#[derive(Component, Debug)]
|
||||
struct Snake;
|
||||
|
||||
// #[derive(Bundle)]
|
||||
// struct SnakeBundle;
|
||||
|
||||
#[derive(Component, Copy, Clone, Debug)]
|
||||
enum Direction {
|
||||
@@ -110,9 +97,14 @@ impl Direction {
|
||||
#[derive(Component, Default, Debug)]
|
||||
struct DirectionBuffer(Option<Direction>);
|
||||
|
||||
#[derive(Component, Default, Debug)]
|
||||
struct Collision {
|
||||
about_to_collide: bool,
|
||||
}
|
||||
|
||||
fn create_snake_segment(commands: &mut Commands, grid_position: grid::Coordinate) -> Entity {
|
||||
commands
|
||||
.spawn_bundle(SpriteBundle {
|
||||
.spawn(SpriteBundle {
|
||||
sprite: Sprite {
|
||||
color: Color::RED,
|
||||
custom_size: Some(Vec2::splat(grid::SEGMENT_SIZE) * 0.9),
|
||||
@@ -135,11 +127,14 @@ fn setup_snake_system(mut commands: Commands) {
|
||||
.insert(SnakeHead);
|
||||
|
||||
commands
|
||||
.spawn()
|
||||
.insert(Snake::with_segments(&[snake_head]))
|
||||
.insert(Name::new("Snake"))
|
||||
.insert(DirectionBuffer::default())
|
||||
.insert_bundle(SpatialBundle::default())
|
||||
.spawn((
|
||||
Snake,
|
||||
Name::new("Snake"),
|
||||
SpatialBundle::default(),
|
||||
DirectionBuffer::default(),
|
||||
Collision::default(),
|
||||
Segments(vec![snake_head]),
|
||||
))
|
||||
.add_child(snake_head);
|
||||
}
|
||||
|
||||
@@ -159,19 +154,19 @@ fn add_direction_system(
|
||||
fn add_tail_system(
|
||||
mut commands: Commands,
|
||||
mut eaten_event_reader: EventReader<fruit::EatenEvent>,
|
||||
mut snake_query: Query<(Entity, &mut Snake)>,
|
||||
mut snake_query: Query<(Entity, &mut Segments), With<Snake>>,
|
||||
) {
|
||||
for _ in eaten_event_reader.iter() {
|
||||
let segment =
|
||||
create_snake_segment(&mut commands, grid::Coordinate::splat(grid::Index::MIN / 2));
|
||||
|
||||
let (snake_entity, mut snake) = snake_query.single_mut();
|
||||
let (snake_entity, mut segments) = snake_query.single_mut();
|
||||
|
||||
snake.segments.push(segment);
|
||||
segments.0.push(segment);
|
||||
|
||||
commands
|
||||
.entity(segment)
|
||||
.insert(Name::new(format!("Segment {}", snake.segments.len())));
|
||||
.insert(Name::new(format!("Segment {}", segments.0.len())));
|
||||
|
||||
commands.entity(snake_entity).add_child(segment);
|
||||
}
|
||||
@@ -215,31 +210,22 @@ fn grid_transform_system(
|
||||
|
||||
fn segments_movement_system(
|
||||
mut segment_query: Query<&mut grid::Coordinate, With<SnakeSegment>>,
|
||||
snake_query: Query<(&Snake, &Direction)>,
|
||||
snake_query: Query<(&Collision, &Direction, &Segments), With<Snake>>,
|
||||
) {
|
||||
for (
|
||||
Snake {
|
||||
about_to_collide,
|
||||
segments,
|
||||
..
|
||||
},
|
||||
direction,
|
||||
) in snake_query.iter()
|
||||
{
|
||||
if *about_to_collide {
|
||||
for (collision, direction, segments) in snake_query.iter() {
|
||||
if collision.about_to_collide {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
// ... then the other elements
|
||||
for (&segment, &previous_segment) in segments.iter().rev().tuple_windows() {
|
||||
for (&segment, &previous_segment) in segments.0.iter().rev().tuple_windows() {
|
||||
let previous_coordinate = *segment_query.get(previous_segment).unwrap();
|
||||
let mut coordinate = segment_query.get_mut(segment).unwrap();
|
||||
*coordinate = previous_coordinate;
|
||||
}
|
||||
|
||||
|
||||
// First move head ...
|
||||
let head = *segments.iter().next().expect("Snake has always a head");
|
||||
let head = *segments.0.first().expect("Snake has always a head");
|
||||
let mut head_coordinate = segment_query.get_mut(head).unwrap();
|
||||
*head_coordinate = next_grid_coordinate(&head_coordinate, direction);
|
||||
}
|
||||
@@ -248,10 +234,10 @@ fn segments_movement_system(
|
||||
fn collision_system(
|
||||
segment_query: Query<&grid::Coordinate, (With<SnakeSegment>, Without<SnakeHead>)>,
|
||||
head_query: Query<(&grid::Coordinate, &Parent), With<SnakeHead>>,
|
||||
mut snake_query: Query<(&Direction, &mut Snake)>,
|
||||
mut snake_query: Query<(&Direction, &mut Collision), With<Snake>>,
|
||||
) {
|
||||
for (head_coordinate, parent) in head_query.iter() {
|
||||
let (direction, mut snake) = snake_query
|
||||
let (direction, mut collision) = snake_query
|
||||
.get_mut(parent.get())
|
||||
.expect("Head must be child of Snake");
|
||||
|
||||
@@ -263,11 +249,11 @@ fn collision_system(
|
||||
.iter()
|
||||
.all(|&coordinate| coordinate != next_head_coordinate);
|
||||
|
||||
snake.about_to_collide = hit_border || hit_snake;
|
||||
collision.about_to_collide = hit_border || hit_snake;
|
||||
}
|
||||
}
|
||||
|
||||
fn game_over_system(query: Query<&Snake>, mut commands: Commands) {
|
||||
fn game_over_system(query: Query<&Collision, With<Snake>>, mut commands: Commands) {
|
||||
if query.get_single().unwrap().about_to_collide {
|
||||
commands.insert_resource(NextState(AppState::End));
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use super::{Snake, SnakeHead, SnakeSegment};
|
||||
use super::{Segments, Snake, SnakeHead, SnakeSegment};
|
||||
use crate::{fruit, tick::TICK_PERIOD};
|
||||
use bevy::prelude::*;
|
||||
use bevy_tweening::{lens::TransformScaleLens, *};
|
||||
@@ -8,11 +8,15 @@ use std::time::Duration;
|
||||
#[component(storage = "SparseSet")]
|
||||
pub(super) struct BulgeMarker;
|
||||
|
||||
#[derive(Resource)]
|
||||
pub(super) struct BulgePropagationTimer(Timer);
|
||||
|
||||
impl Default for BulgePropagationTimer {
|
||||
fn default() -> Self {
|
||||
Self(Timer::new(Duration::from_millis(TICK_PERIOD / 4), true))
|
||||
Self(Timer::new(
|
||||
Duration::from_millis(TICK_PERIOD / 4),
|
||||
TimerMode::Repeating,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,7 +34,7 @@ pub(super) fn add_bulge_system(
|
||||
pub(super) fn propagate_bulge_system(
|
||||
mut commands: Commands,
|
||||
bulge_segment_query: Query<(Entity, &Parent), (With<SnakeSegment>, With<BulgeMarker>)>,
|
||||
snake_query: Query<&Snake>,
|
||||
snake_query: Query<&Segments, With<Snake>>,
|
||||
time: Res<Time>,
|
||||
mut timer: ResMut<BulgePropagationTimer>,
|
||||
) {
|
||||
@@ -43,7 +47,7 @@ pub(super) fn propagate_bulge_system(
|
||||
for (entity, parent) in bulge_segment_query.iter() {
|
||||
commands.entity(entity).remove::<BulgeMarker>();
|
||||
|
||||
let mut segment_iter = snake_query.get(parent.get()).unwrap().segments.iter();
|
||||
let mut segment_iter = snake_query.get(parent.get()).unwrap().0.iter();
|
||||
segment_iter.find(|&&segment_entity| segment_entity == entity);
|
||||
|
||||
if let Some(&segment_entity) = segment_iter.next() {
|
||||
@@ -52,11 +56,13 @@ pub(super) fn propagate_bulge_system(
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn animate_bulge_system(mut commands: Commands, query: Query<Entity, Added<BulgeMarker>>) {
|
||||
pub(super) fn animate_bulge_system(
|
||||
mut commands: Commands,
|
||||
query: Query<Entity, Added<BulgeMarker>>,
|
||||
) {
|
||||
for entity in query.iter() {
|
||||
let tween_to = Tween::new(
|
||||
EaseFunction::QuadraticInOut,
|
||||
TweeningType::Once,
|
||||
Duration::from_millis(100),
|
||||
TransformScaleLens {
|
||||
start: Vec3::splat(1.0),
|
||||
@@ -66,7 +72,6 @@ pub(super) fn animate_bulge_system(mut commands: Commands, query: Query<Entity,
|
||||
|
||||
let tween_back = Tween::new(
|
||||
EaseFunction::QuadraticInOut,
|
||||
TweeningType::Once,
|
||||
Duration::from_millis(150),
|
||||
TransformScaleLens {
|
||||
start: Vec3::splat(1.1),
|
||||
|
||||
@@ -22,7 +22,7 @@ impl Plugin for TickPlugin {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct TickEvent;
|
||||
pub struct TickEvent; // TODO remove again
|
||||
|
||||
fn tick_event_system(mut event_writer: EventWriter<TickEvent>) {
|
||||
event_writer.send(TickEvent);
|
||||
|
||||
Reference in New Issue
Block a user