Проектная работа - WIP
This commit is contained in:
@@ -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)]
|
||||
pub struct Grid;
|
||||
|
||||
+13
-23
@@ -86,6 +86,18 @@ impl Direction {
|
||||
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 {
|
||||
@@ -103,31 +115,9 @@ pub struct Velocity(pub f32);
|
||||
pub struct Inert(pub Direction);
|
||||
|
||||
/// Путь змеи
|
||||
#[derive(Resource, Default, Debug)]
|
||||
#[derive(Resource, Default, Debug, Deref, DerefMut)]
|
||||
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)]
|
||||
mod test {
|
||||
use crate::domain::*;
|
||||
|
||||
+54
-59
@@ -1,75 +1,70 @@
|
||||
use bevy::prelude::*;
|
||||
|
||||
use crate::{
|
||||
domain::{Direction, GRID_SIZE, GridBarier, Head, Inert, SnakePath, Velocity},
|
||||
tools::split_by_grid,
|
||||
domain::{Direction, End, GRID_SIZE, Head, SnakePath, Tail, Velocity},
|
||||
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;
|
||||
|
||||
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) {
|
||||
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();
|
||||
append_snake_path(&transform, &direction);
|
||||
}
|
||||
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 {
|
||||
todo!("получить обновленное направление инерции из SnakePath")
|
||||
if let Some(prev_direction) = snake_path.insert(next_pos, direction) {
|
||||
if direction != prev_direction {
|
||||
transform.rotate_z(PI);
|
||||
}
|
||||
let src = inert.0.get_coord(&transform);
|
||||
let sign = inert.0.get_change_sign();
|
||||
let dst = src + sign * delta;
|
||||
inert.0.set_coord(&mut transform, dst);
|
||||
let transform = transform.clone();
|
||||
commands.trigger(GridBarier::new(entity, (&transform).into()));
|
||||
let direction = direction.clone();
|
||||
commands.queue(move |world: &mut World| {
|
||||
let mut snake_path = world.resource_mut::<SnakePath>();
|
||||
snake_path.push(&transform, direction);
|
||||
});
|
||||
} else {
|
||||
transform.rotate_z(PI / 2.0);
|
||||
}
|
||||
} else if input.just_pressed(KeyCode::ArrowRight) {
|
||||
let (mut transform, direction) = query.into_inner();
|
||||
let next_pos = direction.next_pos(&*transform);
|
||||
let mut direction = direction.clone();
|
||||
direction.rotate_right();
|
||||
if let Some(prev_direction) = snake_path.insert(next_pos, direction) {
|
||||
if direction != prev_direction {
|
||||
transform.rotate_z(-PI);
|
||||
}
|
||||
} 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);
|
||||
trace!("\tsplit_by_grid({:?}, {:?}, {:?}) -> {:?}", src, dst, grid, result);
|
||||
result
|
||||
/// Система движения змеи
|
||||
pub fn snake_moving(
|
||||
time: Res<Time<Fixed>>,
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user