Add eating animation
This commit is contained in:
17
Cargo.lock
generated
17
Cargo.lock
generated
@@ -246,6 +246,7 @@ version = "0.1.0"
|
||||
dependencies = [
|
||||
"bevy",
|
||||
"bevy_editor_pls",
|
||||
"bevy_tweening",
|
||||
"itertools",
|
||||
"iyes_loopless",
|
||||
"rand",
|
||||
@@ -880,6 +881,16 @@ dependencies = [
|
||||
"bevy_reflect",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bevy_tweening"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "164bcb41708fa1aeb435b6bba6cae61777b9f8cf3e18b207bb6209ca5b970e77"
|
||||
dependencies = [
|
||||
"bevy",
|
||||
"interpolation",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bevy_ui"
|
||||
version = "0.8.1"
|
||||
@@ -2012,6 +2023,12 @@ dependencies = [
|
||||
"web-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "interpolation"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d3b7357d2bbc5ee92f8e899ab645233e43d21407573cceb37fed8bc3dede2c02"
|
||||
|
||||
[[package]]
|
||||
name = "io-kit-sys"
|
||||
version = "0.2.0"
|
||||
|
||||
@@ -11,6 +11,7 @@ itertools = "0.10.3"
|
||||
# bevy-inspector-egui = "0.12.1"
|
||||
rand = "0.8.5"
|
||||
bevy_editor_pls = { git = "https://github.com/jakobhellermann/bevy_editor_pls" }
|
||||
bevy_tweening = "0.5.0"
|
||||
|
||||
[dependencies.bevy]
|
||||
version = "0.8.0"
|
||||
|
||||
@@ -29,10 +29,7 @@ fn eaten_event_sent(mut eaten_event_reader: EventReader<EatenEvent>) -> bool {
|
||||
eaten_event_reader.iter().count() != 0
|
||||
}
|
||||
|
||||
fn spawn_fruit_system(
|
||||
mut commands: Commands,
|
||||
coordinate_query: Query<&grid::Coordinate>,
|
||||
) {
|
||||
fn spawn_fruit_system(mut commands: Commands, coordinate_query: Query<&grid::Coordinate>) {
|
||||
fn random_coordinate() -> grid::Coordinate {
|
||||
let mut rng = rand::thread_rng();
|
||||
let coordinate_range = 0..grid::SIZE;
|
||||
@@ -49,7 +46,7 @@ fn spawn_fruit_system(
|
||||
.any(|&snake_coordinate| snake_coordinate == coordinate)
|
||||
};
|
||||
|
||||
let fruit_coordinate = std::iter::repeat(random_coordinate())
|
||||
let fruit_coordinate = std::iter::repeat_with(random_coordinate)
|
||||
.find(|&coordinate| !coordinate_in_other_element(coordinate))
|
||||
.expect("Should always be found.");
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ use bevy::{prelude::*, render::camera::ScalingMode};
|
||||
use bevy_editor_pls::prelude::*;
|
||||
use grid::{SEGMENT_SIZE, SIZE};
|
||||
use iyes_loopless::prelude::*;
|
||||
use bevy_tweening::TweeningPlugin;
|
||||
|
||||
mod canvas;
|
||||
mod fruit;
|
||||
@@ -35,6 +36,7 @@ fn main() {
|
||||
.add_loopless_state(AppState::Begin)
|
||||
.add_plugins(DefaultPlugins)
|
||||
.add_plugin(EditorPlugin)
|
||||
.add_plugin(TweeningPlugin)
|
||||
.add_plugin(TickPlugin)
|
||||
.add_plugin(SnakePlugin)
|
||||
.add_plugin(FruitPlugin)
|
||||
|
||||
85
src/snake.rs
85
src/snake.rs
@@ -1,7 +1,9 @@
|
||||
use crate::{fruit, grid, tick::tick_triggered, AppState};
|
||||
use bevy::prelude::*;
|
||||
use bevy_tweening::{lens::TransformScaleLens, *};
|
||||
use itertools::Itertools;
|
||||
use iyes_loopless::prelude::*;
|
||||
use std::time::Duration;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash, StageLabel)]
|
||||
struct MovementStage;
|
||||
@@ -17,7 +19,8 @@ impl Plugin for SnakePlugin {
|
||||
fn build(&self, app: &mut App) {
|
||||
let movement_stage = SystemStage::parallel();
|
||||
|
||||
app.add_startup_system(setup_snake_system)
|
||||
app.insert_resource(BulgePropagationTimer::default())
|
||||
.add_startup_system(setup_snake_system)
|
||||
.add_stage_after(CoreStage::Update, MovementStage, movement_stage)
|
||||
.add_system_to_stage(
|
||||
MovementStage,
|
||||
@@ -49,7 +52,10 @@ impl Plugin for SnakePlugin {
|
||||
.add_system(add_direction_system.run_in_state(AppState::Begin))
|
||||
.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);
|
||||
.add_system(add_tail_system)
|
||||
.add_system(add_bulge_system)
|
||||
.add_system(propagate_bulge_system)
|
||||
.add_system(animate_bulge_system);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -78,6 +84,18 @@ struct Snake;
|
||||
#[derive(Component)]
|
||||
struct SnakeSegments(Vec<Entity>);
|
||||
|
||||
#[derive(Component)]
|
||||
#[component(storage = "SparseSet")]
|
||||
struct BulgeMarker;
|
||||
|
||||
struct BulgePropagationTimer(Timer);
|
||||
|
||||
impl Default for BulgePropagationTimer {
|
||||
fn default() -> Self {
|
||||
Self(Timer::new(Duration::from_millis(30), true))
|
||||
}
|
||||
}
|
||||
|
||||
impl SnakeSegments {
|
||||
fn with_head(snake_head: Entity) -> Self {
|
||||
Self(vec![snake_head])
|
||||
@@ -167,6 +185,69 @@ fn add_tail_system(
|
||||
}
|
||||
}
|
||||
|
||||
fn add_bulge_system(
|
||||
mut commands: Commands,
|
||||
mut eaten_event_reader: EventReader<fruit::EatenEvent>,
|
||||
query: Query<Entity, With<SnakeHead>>,
|
||||
) {
|
||||
for _ in eaten_event_reader.iter() {
|
||||
let snake_head_entity = query.single();
|
||||
commands.entity(snake_head_entity).insert(BulgeMarker);
|
||||
}
|
||||
}
|
||||
|
||||
fn propagate_bulge_system(
|
||||
mut commands: Commands,
|
||||
query: Query<(Entity, &Parent), (With<SnakeSegment>, With<BulgeMarker>)>,
|
||||
snake_segments_query: Query<&SnakeSegments>,
|
||||
time: Res<Time>,
|
||||
mut timer: ResMut<BulgePropagationTimer>,
|
||||
) {
|
||||
timer.0.tick(time.delta());
|
||||
|
||||
if !timer.0.finished() {
|
||||
return;
|
||||
}
|
||||
|
||||
for (entity, parent) in query.iter() {
|
||||
commands.entity(entity).remove::<BulgeMarker>();
|
||||
let mut segment_iter = snake_segments_query.get(parent.get()).unwrap().0.iter();
|
||||
segment_iter.find(|&&segment_entity| segment_entity == entity);
|
||||
|
||||
if let Some(&segment_entity) = segment_iter.next() {
|
||||
commands.entity(segment_entity).insert(BulgeMarker);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn animate_bulge_system(mut commands: Commands, query: Query<Entity, Added<BulgeMarker>>) {
|
||||
for entity in query.iter() {
|
||||
let tween_to = Tween::new(
|
||||
EaseFunction::CubicInOut,
|
||||
TweeningType::Once,
|
||||
Duration::from_millis(100),
|
||||
TransformScaleLens {
|
||||
start: Vec3::splat(1.0),
|
||||
end: Vec3::splat(1.1),
|
||||
},
|
||||
);
|
||||
|
||||
let tween_back = Tween::new(
|
||||
EaseFunction::CubicInOut,
|
||||
TweeningType::Once,
|
||||
Duration::from_millis(150),
|
||||
TransformScaleLens {
|
||||
start: Vec3::splat(1.1),
|
||||
end: Vec3::splat(1.0),
|
||||
},
|
||||
);
|
||||
|
||||
let tween = tween_to.then(tween_back);
|
||||
|
||||
commands.entity(entity).insert(Animator::new(tween));
|
||||
}
|
||||
}
|
||||
|
||||
fn update_direction_system(
|
||||
mut query: Query<(&mut Direction, &mut DirectionBuffer), With<SnakeHead>>,
|
||||
) {
|
||||
|
||||
Reference in New Issue
Block a user