diff --git a/snake-game/src/gameplay.rs b/snake-game/src/gameplay.rs index 2991d7f..75ad1c3 100644 --- a/snake-game/src/gameplay.rs +++ b/snake-game/src/gameplay.rs @@ -1,9 +1,9 @@ use bevy::prelude::*; -use crate::domain::{Direction, GRID_SIZE, GridBarier, Head, Inert, SnakePath, Velocity}; - -mod tools; -use tools::*; +use crate::{ + domain::{Direction, GRID_SIZE, GridBarier, Head, Inert, SnakePath, Velocity}, + tools::split_by_grid, +}; /// Система поворота головы змеи pub fn head_rotation( diff --git a/snake-game/src/lib.rs b/snake-game/src/lib.rs index ebad4e3..22a2e3e 100644 --- a/snake-game/src/lib.rs +++ b/snake-game/src/lib.rs @@ -40,6 +40,7 @@ pub fn define_log_layer() -> Option { mod domain; mod gameplay; mod startup; +mod tools; pub use gameplay::{head_rotation, moving}; pub use startup::{print_all_entities, setup_frame_rate, startup}; diff --git a/snake-game/src/startup.rs b/snake-game/src/startup.rs index 80ff026..6b42cfd 100644 --- a/snake-game/src/startup.rs +++ b/snake-game/src/startup.rs @@ -1,7 +1,10 @@ -use bevy::{ecs::observer::ObservedBy, prelude::*, winit::WinitSettings}; +use bevy::{prelude::*, winit::WinitSettings}; use std::time::Duration; -use crate::domain::{End, Grid, GridBarier, SnakePath, Tail}; +use crate::{ + domain::{End, Grid, SnakePath, Tail}, + tools::{end_observer, schedule_set_velocity}, +}; /// Настройка частоты кадров pub fn setup_frame_rate(mut winit: ResMut) { @@ -37,7 +40,7 @@ fn spawn_snake(commands: &mut Commands) { vec2(HEAD_SIZE as f32, HEAD_SIZE as f32), ), Transform { - translation: vec3(0.0, 0.0, 0.0), + translation: vec3(0.0, 0.0, 1.0), ..Default::default() }, )) @@ -82,46 +85,8 @@ fn spawn_snake(commands: &mut Commands) { }, )) .id(); - - commands.entity(head).observe( - move |event: On, - mut commands: Commands, - mut query: Query<&mut Velocity, With>| { - if let Ok(mut velocity) = query.get_mut(tail) { - velocity.0 = SNAKE_VELOCITY as f32; - } - commands.entity(event.0).remove::(); - }, - ); - - commands - .entity(tail) - .observe( - |event: On, - mut query: Query<(&mut Direction, &Transform)>, - snake_path: Res| { - if let Ok((mut direction, transform)) = query.get_mut(event.0) { - if let Some(new_direction) = snake_path.pick(transform) { - trace!("change direction for {:?} to {:?}", event.0, new_direction); - *direction = new_direction; - } - } - }, - ) - .observe( - |event: On, - query: Query<(Entity, &Transform), With>, - mut snake_path: ResMut| { - if let Ok((entity, transform)) = query.get(event.0) { - if let Some(removed) = snake_path.pop(transform) { - trace!( - "removed direction {:?} from snake_path by End entity {:?}", - removed, entity - ); - } - } - }, - ); + commands.entity(head).observe(schedule_set_velocity(tail)); + commands.entity(tail).observe(end_observer); } /// Создать координатную сетку diff --git a/snake-game/src/gameplay/tools.rs b/snake-game/src/tools.rs similarity index 62% rename from snake-game/src/gameplay/tools.rs rename to snake-game/src/tools.rs index 9231b2d..76ed419 100644 --- a/snake-game/src/gameplay/tools.rs +++ b/snake-game/src/tools.rs @@ -1,3 +1,7 @@ +use bevy::{ecs::observer::ObservedBy, prelude::*}; + +use crate::domain::*; + /// Разбиение изменения координаты по границам сетки pub fn split_by_grid(src: f32, dst: f32, grid: f32) -> Vec<(f32, f32)> { if grid <= 0.0 { @@ -36,9 +40,55 @@ pub fn split_by_grid(src: f32, dst: f32, grid: f32) -> Vec<(f32, f32)> { output } +#[allow(unused)] +/// Слушатель событий [GridBarier] для хвоста, обновляющий направление его движения из ресурса [SnakePath] +pub fn tail_observer( + event: On, + mut query: Query<(&mut Direction, &Transform), Without>, + snake_path: Res, +) { + if let Ok((mut direction, transform)) = query.get_mut(event.0) { + if let Some(new_direction) = snake_path.pick(transform) { + trace!("change direction for {:?} to {:?}", event.0, new_direction); + *direction = new_direction; + } + } +} + +/// Слушатель событий [GridBarier] для конца змеи, обновляющий направление его движения из ресурса [SnakePath] и удаляющий полученные значения из [SnakePath] +pub fn end_observer( + event: On, + mut query: Query<(&mut Direction, &Transform), With>, + mut snake_path: ResMut, +) { + if let Ok((mut direction, transform)) = query.get_mut(event.0) { + if let Some(new_direction) = snake_path.pop(transform) { + trace!( + "change direction for {:?} to {:?} and remove it from SnakePath", + event.0, new_direction + ); + *direction = new_direction; + } + } +} + +/// Запланировать установку скорости движения [Velocity] при следующем событии [GridBarier] +pub fn schedule_set_velocity( + tail: Entity, +) -> impl Fn(On, Commands, Query<&mut Velocity, With>) { + move |event: On, + mut commands: Commands, + mut query: Query<&mut Velocity, With>| { + if let Ok(mut velocity) = query.get_mut(tail) { + velocity.0 = SNAKE_VELOCITY as f32; + } + commands.entity(event.0).remove::(); + } +} + #[cfg(test)] mod test { - use crate::gameplay::*; + use crate::tools::*; #[test] fn test_split_by_grid() {