Проектная работа - WIP
This commit is contained in:
@@ -2,7 +2,7 @@ use std::{fmt::Display, ops::Deref};
|
|||||||
|
|
||||||
use bevy::transform::components::Transform;
|
use bevy::transform::components::Transform;
|
||||||
|
|
||||||
use crate::domain::GRID_SIZE;
|
use crate::domain::{Direction, GRID_SIZE};
|
||||||
|
|
||||||
#[derive(Clone, Copy, Default, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
#[derive(Clone, Copy, Default, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
pub struct Position {
|
pub struct Position {
|
||||||
@@ -14,6 +14,15 @@ impl Position {
|
|||||||
pub fn new(x: i8, y: i8) -> Self {
|
pub fn new(x: i8, y: i8) -> Self {
|
||||||
Self { x, y }
|
Self { x, y }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn change(&mut self, direction: &Direction) {
|
||||||
|
match direction {
|
||||||
|
Direction::Up => self.y += 1,
|
||||||
|
Direction::Left => self.x -= 1,
|
||||||
|
Direction::Down => self.y -= 1,
|
||||||
|
Direction::Right => self.x += 1,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for Position {
|
impl Display for Position {
|
||||||
|
|||||||
@@ -1,8 +1,54 @@
|
|||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
use std::{collections::HashMap, fmt::Debug};
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use crate::domain::{Direction, Position};
|
use crate::domain::{Direction, Position};
|
||||||
|
|
||||||
/// Путь змеи
|
/// Путь змеи
|
||||||
#[derive(Resource, Default, Debug, Deref, DerefMut)]
|
#[derive(Resource)]
|
||||||
pub struct SnakePath(HashMap<Position, Direction>);
|
pub struct SnakePath {
|
||||||
|
positions: HashMap<Position, Direction>,
|
||||||
|
fresh: Option<Position>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SnakePath {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
SnakePath {
|
||||||
|
positions: HashMap::with_capacity(16),
|
||||||
|
fresh: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn push(&mut self, position: Position, direction: Direction) -> bool {
|
||||||
|
if let Some(_) = self.positions.get(&position) {
|
||||||
|
if let Some(fresh) = self.fresh {
|
||||||
|
if position == fresh {
|
||||||
|
self.positions.insert(position, direction);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
self.positions.insert(position, direction);
|
||||||
|
self.fresh = Some(position);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn peek(&mut self, position: &Position) -> Option<Direction> {
|
||||||
|
if let Some(fresh) = self.fresh {
|
||||||
|
if fresh == *position {
|
||||||
|
self.fresh = None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.positions.get(position).cloned()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn drop(&mut self, position: &Position) {
|
||||||
|
self.positions.remove(position);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for SnakePath {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
+19
-11
@@ -15,20 +15,32 @@ pub fn head_rotation(
|
|||||||
let (mut transform, direction) = query.into_inner();
|
let (mut transform, direction) = query.into_inner();
|
||||||
let translation = transform.translation.clone();
|
let translation = transform.translation.clone();
|
||||||
let cur_pos = Position::from(&*transform);
|
let cur_pos = Position::from(&*transform);
|
||||||
let dst_pos = direction.dst_pos(&*transform);
|
let mut dst_pos = direction.dst_pos(&*transform);
|
||||||
let mut new_direction = direction.clone();
|
let mut new_direction = direction.clone();
|
||||||
new_direction.rotate_left();
|
new_direction.rotate_left();
|
||||||
snake_path.insert(dst_pos, new_direction);
|
if !snake_path.push(dst_pos, new_direction) {
|
||||||
|
trace!("try 1 failed: cannot push [{dst_pos} => {new_direction}] into SnakePath");
|
||||||
|
dst_pos.change(&direction);
|
||||||
|
if !snake_path.push(dst_pos, new_direction) {
|
||||||
|
trace!("try 2 failed: cannot push [{dst_pos} => {new_direction}] into SnakePath");
|
||||||
|
}
|
||||||
|
}
|
||||||
transform.rotation = new_direction.orientation();
|
transform.rotation = new_direction.orientation();
|
||||||
trace!("running {direction} at {cur_pos} {translation}: go {new_direction} on {dst_pos}");
|
trace!("running {direction} at {cur_pos} {translation}: go {new_direction} on {dst_pos}");
|
||||||
} else if input.just_pressed(KeyCode::ArrowRight) {
|
} else if input.just_pressed(KeyCode::ArrowRight) {
|
||||||
let (mut transform, direction) = query.into_inner();
|
let (mut transform, direction) = query.into_inner();
|
||||||
let translation = transform.translation.clone();
|
let translation = transform.translation.clone();
|
||||||
let cur_pos = Position::from(&*transform);
|
let cur_pos = Position::from(&*transform);
|
||||||
let dst_pos = direction.dst_pos(&*transform);
|
let mut dst_pos = direction.dst_pos(&*transform);
|
||||||
let mut new_direction = direction.clone();
|
let mut new_direction = direction.clone();
|
||||||
new_direction.rotate_right();
|
new_direction.rotate_right();
|
||||||
snake_path.insert(dst_pos, new_direction);
|
if !snake_path.push(dst_pos, new_direction) {
|
||||||
|
trace!("try 1 failed: cannot push [{dst_pos} => {new_direction}] into SnakePath");
|
||||||
|
dst_pos.change(&direction);
|
||||||
|
if !snake_path.push(dst_pos, new_direction) {
|
||||||
|
trace!("try 2 failed: cannot push [{dst_pos} => {new_direction}] into SnakePath");
|
||||||
|
}
|
||||||
|
}
|
||||||
transform.rotation = new_direction.orientation();
|
transform.rotation = new_direction.orientation();
|
||||||
trace!("running {direction} at {cur_pos} {translation}: go {new_direction} on {dst_pos}");
|
trace!("running {direction} at {cur_pos} {translation}: go {new_direction} on {dst_pos}");
|
||||||
}
|
}
|
||||||
@@ -37,7 +49,7 @@ pub fn head_rotation(
|
|||||||
/// Система движения змеи
|
/// Система движения змеи
|
||||||
pub fn snake_moving(
|
pub fn snake_moving(
|
||||||
time: Res<Time<Fixed>>,
|
time: Res<Time<Fixed>>,
|
||||||
snake_path: Res<SnakePath>,
|
mut snake_path: ResMut<SnakePath>,
|
||||||
query: Query<(&mut Transform, &mut Direction, &Velocity, Entity, Has<End>), Or<(With<Head>, With<Tail>, With<End>)>>,
|
query: Query<(&mut Transform, &mut Direction, &Velocity, Entity, Has<End>), Or<(With<Head>, With<Tail>, With<End>)>>,
|
||||||
mut commands: Commands,
|
mut commands: Commands,
|
||||||
) {
|
) {
|
||||||
@@ -55,7 +67,7 @@ pub fn snake_moving(
|
|||||||
if let Some(second) = splited.next() {
|
if let Some(second) = splited.next() {
|
||||||
let delta = second.1.abs();
|
let delta = second.1.abs();
|
||||||
let pos = Position::from(&*transform);
|
let pos = Position::from(&*transform);
|
||||||
if let Some(dir) = snake_path.get(&pos) {
|
if let Some(dir) = snake_path.peek(&pos) {
|
||||||
trace!("set new direction for {entity} in {pos} --> {dir}");
|
trace!("set new direction for {entity} in {pos} --> {dir}");
|
||||||
*direction = dir.clone();
|
*direction = dir.clone();
|
||||||
}
|
}
|
||||||
@@ -69,11 +81,7 @@ pub fn snake_moving(
|
|||||||
|
|
||||||
// если это кончик хвоста, то нужно очистить [SnakePath] за собой
|
// если это кончик хвоста, то нужно очистить [SnakePath] за собой
|
||||||
if has_end {
|
if has_end {
|
||||||
commands.queue(move |world: &mut World| {
|
snake_path.drop(&pos);
|
||||||
if let Some(mut snake_path) = world.get_resource_mut::<SnakePath>() {
|
|
||||||
snake_path.remove(&pos);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user