Проектная работа - WIP

This commit is contained in:
3 changed files with 73 additions and 82 deletions
+6
View File
@@ -42,6 +42,12 @@ pub fn time_speed(input: Res<ButtonInput<KeyCode>>, mut time: ResMut<Time<Virtua
} }
} }
fn _split_by_grid_tracing(src: f32, dst: f32, grid: f32) -> Vec<(f32, f32)> {
let result = crate::tools::split_by_grid(src, dst, grid);
trace!("\tsplit_by_grid({:?}, {:?}, {:?}) -> {:?}", src, dst, grid, result);
result
}
/// Координатная сетка /// Координатная сетка
#[derive(Component)] #[derive(Component)]
pub struct Grid; pub struct Grid;
+13 -23
View File
@@ -86,6 +86,18 @@ impl Direction {
Direction::Left | Direction::Right => vec.translation.x = value, Direction::Left | Direction::Right => vec.translation.x = value,
} }
} }
/// Получить следующую по направлению координатную позицию
pub fn next_pos(&self, transform: &Transform) -> Position {
let mut pos = Position::from(transform);
match self {
Direction::Up => pos.y += 1,
Direction::Left => pos.x -= 1,
Direction::Down => pos.y -= 1,
Direction::Right => pos.x += 1,
};
pos
}
} }
impl Default for Direction { impl Default for Direction {
@@ -103,31 +115,9 @@ pub struct Velocity(pub f32);
pub struct Inert(pub Direction); pub struct Inert(pub Direction);
/// Путь змеи /// Путь змеи
#[derive(Resource, Default, Debug)] #[derive(Resource, Default, Debug, Deref, DerefMut)]
pub struct SnakePath(HashMap<Position, Direction>); pub struct SnakePath(HashMap<Position, Direction>);
impl SnakePath {
pub fn push(&mut self, transform: &Transform, direction: Direction) -> (Position, Direction) {
let key = transform.into();
self.0.insert(key, direction.clone());
(key, direction.clone())
}
pub fn pick(&self, transform: &Transform) -> Option<(Position, Direction)> {
let key = transform.into();
self.0.get(&key).cloned().map(|d| (key, d))
}
pub fn drop(&mut self, transform: &Transform) -> Option<(Position, Direction)> {
let key = transform.into();
self.0.remove(&key).map(|d| (key, d))
}
pub fn debug(&self) -> impl Debug {
&self.0
}
}
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use crate::domain::*; use crate::domain::*;
+52 -57
View File
@@ -1,75 +1,70 @@
use bevy::prelude::*; use bevy::prelude::*;
use crate::{ use crate::{
domain::{Direction, GRID_SIZE, GridBarier, Head, Inert, SnakePath, Velocity}, domain::{Direction, End, GRID_SIZE, Head, SnakePath, Tail, Velocity},
tools::split_by_grid, tools::{Position, split_by_grid},
}; };
/// Система поворота головы змеи /// Система поворота головы змеи
pub fn head_rotation(input: Res<ButtonInput<KeyCode>>, query: Single<(&mut Transform, &mut Direction), With<Head>>, mut snake_path: ResMut<SnakePath>) { pub fn head_rotation(
input: Res<ButtonInput<KeyCode>>, //
query: Single<(&mut Transform, &Direction), With<Head>>,
mut snake_path: ResMut<SnakePath>,
) {
use core::f32::consts::PI; use core::f32::consts::PI;
let (mut transform, mut direction) = query.into_inner();
let mut append_snake_path = |transform: &Transform, direction: &Direction| {
snake_path.push(&transform, direction.clone());
trace!("append snake_path: {:?}", snake_path);
};
if input.just_pressed(KeyCode::ArrowLeft) { if input.just_pressed(KeyCode::ArrowLeft) {
transform.rotate_z(PI / 2.0); let (mut transform, direction) = query.into_inner();
let next_pos = direction.next_pos(&*transform);
let mut direction = direction.clone();
direction.rotate_left(); direction.rotate_left();
append_snake_path(&transform, &direction); if let Some(prev_direction) = snake_path.insert(next_pos, direction) {
if direction != prev_direction {
transform.rotate_z(PI);
} }
if input.just_pressed(KeyCode::ArrowRight) {
transform.rotate_z(-PI / 2.0);
direction.rotate_right();
append_snake_path(&transform, &direction);
}
}
/// Система движения для всех движущихся сущностей
pub fn moving(time: Res<Time<Fixed>>, query: Query<(&mut Transform, &mut Inert, Option<&Direction>, &Velocity, Entity)>, mut commands: Commands) {
// для всех сущностей, обладающих позицией, инерцией, направлением (опционально) и скоростью
for (mut transform, mut inert, direction, Velocity(velocity), entity) in query.into_iter() {
// используя скорость и время получаем величину перемещения
let delta = velocity * time.delta_secs();
// используя направление инерции получаем получаем исходное значение изменяемой координаты и знак изменения ('+' или '-')
let src = inert.0.get_coord(&transform);
let sign = inert.0.get_change_sign();
// используя полученные данные получаем целевое значение координаты
let dst = src + sign * delta;
// разбиваем путь от исходного до целевого значения координаты по границам сетки
let mut splited = split_by_grid(src, dst, GRID_SIZE as f32).into_iter();
// берем первый сегмент разбитого пути и обновляем позицию
let first = splited.next().unwrap_or((0.0, 0.0));
inert.0.set_coord(&mut transform, first.0);
// если разбивка содержит дополнительный сегмент то обрабатываем его
if let Some(second) = splited.next() {
// из дополнительного сегмента берем величину изменения
let delta = second.1.abs();
if let Some(direction) = direction {
inert.0 = *direction;
} else { } else {
todo!("получить обновленное направление инерции из SnakePath") transform.rotate_z(PI / 2.0);
} }
let src = inert.0.get_coord(&transform); } else if input.just_pressed(KeyCode::ArrowRight) {
let sign = inert.0.get_change_sign(); let (mut transform, direction) = query.into_inner();
let dst = src + sign * delta; let next_pos = direction.next_pos(&*transform);
inert.0.set_coord(&mut transform, dst); let mut direction = direction.clone();
let transform = transform.clone(); direction.rotate_right();
commands.trigger(GridBarier::new(entity, (&transform).into())); if let Some(prev_direction) = snake_path.insert(next_pos, direction) {
let direction = direction.clone(); if direction != prev_direction {
commands.queue(move |world: &mut World| { transform.rotate_z(-PI);
let mut snake_path = world.resource_mut::<SnakePath>(); }
snake_path.push(&transform, direction); } else {
}); transform.rotate_z(-PI / 2.0);
} }
} }
} }
fn _split_by_grid_tracing(src: f32, dst: f32, grid: f32) -> Vec<(f32, f32)> { /// Система движения змеи
let result = split_by_grid(src, dst, grid); pub fn snake_moving(
trace!("\tsplit_by_grid({:?}, {:?}, {:?}) -> {:?}", src, dst, grid, result); time: Res<Time<Fixed>>,
result snake_path: Res<SnakePath>,
query: Query<(&mut Transform, &mut Direction, &Velocity), Or<(With<Head>, With<Tail>, With<End>)>>,
) {
for (mut transform, mut direction, Velocity(velocity)) in query.into_iter() {
let delta = velocity * time.delta_secs();
let src = direction.get_coord(&transform);
let sign = direction.get_change_sign();
let dst = src + sign * delta;
let mut splited = split_by_grid(src, dst, GRID_SIZE as f32).into_iter();
let first = splited.next().unwrap_or((0.0, 0.0));
direction.set_coord(&mut transform, first.0);
if let Some(second) = splited.next() {
let delta = second.1.abs();
let pos = Position::from(&*transform);
if let Some(dir) = snake_path.get(&pos) {
trace!("set new direction in {pos:?} --> {dir:?}");
*direction = dir.clone();
}
let src = direction.get_coord(&*transform);
let sign = direction.get_change_sign();
let dst = src + sign * delta;
direction.set_coord(&mut transform, dst);
}
}
} }