Проектная работа - WIP
This commit is contained in:
@@ -8,11 +8,7 @@ pub fn print_all_entities(mut commands: Commands, query: Query<Entity>) {
|
||||
}
|
||||
|
||||
/// ДЛЯ ОТЛАДКИ - вывод всех сущностей мира по нажатию Enter
|
||||
pub fn print_all_entities_by_press_enter(
|
||||
input: Res<ButtonInput<KeyCode>>,
|
||||
mut commands: Commands,
|
||||
query: Query<Entity>,
|
||||
) {
|
||||
pub fn print_all_entities_by_press_enter(input: Res<ButtonInput<KeyCode>>, mut commands: Commands, query: Query<Entity>) {
|
||||
if input.just_pressed(KeyCode::Enter) {
|
||||
for entity in query {
|
||||
commands.entity(entity).log_components();
|
||||
@@ -28,9 +24,7 @@ pub struct Grid;
|
||||
pub fn spawn_grid(commands: &mut Commands) {
|
||||
use crate::domain::GRID_SIZE;
|
||||
|
||||
let grid = commands
|
||||
.spawn((Grid, Transform::default(), Visibility::default()))
|
||||
.id();
|
||||
let grid = commands.spawn((Grid, Transform::default(), Visibility::default())).id();
|
||||
|
||||
for x in -20..=20 {
|
||||
commands.spawn((
|
||||
|
||||
+32
-21
@@ -1,7 +1,9 @@
|
||||
use std::collections::HashMap;
|
||||
use std::{collections::HashMap, fmt::Debug};
|
||||
|
||||
use bevy::prelude::*;
|
||||
|
||||
use crate::tools::Position;
|
||||
|
||||
pub const GRID_SIZE: u8 = 48;
|
||||
pub const HEAD_SIZE: u8 = (GRID_SIZE as f32 * 1.1) as u8;
|
||||
pub const SNAKE_VELOCITY: u8 = (GRID_SIZE as f32 / 1.0) as u8;
|
||||
@@ -20,7 +22,19 @@ pub struct End;
|
||||
|
||||
/// Событие прохождения границы сетки
|
||||
#[derive(EntityEvent)]
|
||||
pub struct GridBarier(pub Entity);
|
||||
pub struct GridBarier {
|
||||
pub entity: Entity,
|
||||
#[allow(unused)]
|
||||
pub src_pos: Position,
|
||||
#[allow(unused)]
|
||||
pub dst_pos: Position,
|
||||
}
|
||||
|
||||
impl GridBarier {
|
||||
pub fn new(entity: Entity, src_pos: Position, dst_pos: Position) -> Self {
|
||||
Self { entity, src_pos, dst_pos }
|
||||
}
|
||||
}
|
||||
|
||||
/// Направление движения
|
||||
#[derive(Component, PartialEq, Clone, Copy, Debug)]
|
||||
@@ -93,30 +107,27 @@ pub struct Inert(pub Direction);
|
||||
|
||||
/// Путь змеи
|
||||
#[derive(Resource, Default, Debug)]
|
||||
pub struct SnakePath(HashMap<(i16, i16), Direction>);
|
||||
pub struct SnakePath(HashMap<Position, Direction>);
|
||||
|
||||
impl SnakePath {
|
||||
fn to_key(transform: &Transform) -> (i16, i16) {
|
||||
(
|
||||
(transform.translation.x / GRID_SIZE as f32).floor() as i16,
|
||||
(transform.translation.y / GRID_SIZE as f32).floor() as i16,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn push(&mut self, transform: &Transform, direction: Direction) -> (i16, i16, Direction) {
|
||||
let key = SnakePath::to_key(transform);
|
||||
pub fn push(&mut self, transform: &Transform, direction: Direction) -> (Position, Direction) {
|
||||
let key = transform.into();
|
||||
self.0.insert(key, direction.clone());
|
||||
(key.0, key.1, direction.clone())
|
||||
(key, direction.clone())
|
||||
}
|
||||
|
||||
pub fn pick(&self, transform: &Transform) -> Option<(i16, i16, Direction)> {
|
||||
let key = SnakePath::to_key(transform);
|
||||
self.0.get(&key).cloned().map(|d| (key.0, key.1, d))
|
||||
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<(i16, i16, Direction)> {
|
||||
let key = SnakePath::to_key(transform);
|
||||
self.0.remove(&key).map(|d| (key.0, key.1, 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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -132,10 +143,10 @@ mod test {
|
||||
snake_path.push(&Transform::default(), Direction::default());
|
||||
assert_eq!(snake_path.0.len(), 1);
|
||||
|
||||
assert!(snake_path.pick(&Transform::default()) == Some((0, 0, Direction::default())));
|
||||
assert!(snake_path.pick(&Transform::default()) == Some((Position::default(), Direction::default())));
|
||||
assert_eq!(snake_path.0.len(), 1);
|
||||
|
||||
assert!(snake_path.drop(&Transform::default()) == Some((0, 0, Direction::default())));
|
||||
assert!(snake_path.drop(&Transform::default()) == Some((Position::default(), Direction::default())));
|
||||
assert_eq!(snake_path.0.len(), 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,11 +6,7 @@ use crate::{
|
||||
};
|
||||
|
||||
/// Система поворота головы змеи
|
||||
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, &mut Direction), With<Head>>, mut snake_path: ResMut<SnakePath>) {
|
||||
use core::f32::consts::PI;
|
||||
|
||||
let (mut transform, mut direction) = query.into_inner();
|
||||
@@ -33,17 +29,14 @@ pub fn head_rotation(
|
||||
}
|
||||
|
||||
/// Система движения для всех движущихся сущностей
|
||||
pub fn moving(
|
||||
time: Res<Time<Fixed>>,
|
||||
query: Query<(&mut Transform, &mut Inert, &Direction, &Velocity, Entity)>,
|
||||
mut commands: Commands,
|
||||
) {
|
||||
pub fn moving(time: Res<Time<Fixed>>, query: Query<(&mut Transform, &mut Inert, &Direction, &Velocity, Entity)>, mut commands: Commands) {
|
||||
for (mut transform, mut inert, direction, Velocity(velocity), entity) in query.into_iter() {
|
||||
let src_transftorm = transform.clone();
|
||||
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_tracing(src, dst, GRID_SIZE as f32).into_iter();
|
||||
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() {
|
||||
@@ -53,16 +46,13 @@ pub fn moving(
|
||||
let sign = inert.0.get_change_sign();
|
||||
let dst = src + sign * delta;
|
||||
inert.0.set_coord(&mut transform, dst);
|
||||
commands.trigger(GridBarier(entity));
|
||||
commands.trigger(GridBarier::new(entity, (&src_transftorm).into(), transform.into()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
);
|
||||
trace!("\tsplit_by_grid({:?}, {:?}, {:?}) -> {:?}", src, dst, grid, result);
|
||||
result
|
||||
}
|
||||
|
||||
+19
-30
@@ -4,18 +4,12 @@ use bevy::prelude::*;
|
||||
|
||||
#[allow(unused)]
|
||||
/// Слушатель событий [GridBarier] для хвоста, обновляющий направление его движения из ресурса [SnakePath] и позволяющий следовать за головой
|
||||
pub fn tail_observer(
|
||||
event: On<GridBarier>,
|
||||
mut query: Query<(&mut Direction, &Transform)>,
|
||||
snake_path: Res<SnakePath>,
|
||||
) {
|
||||
if event.observer() == event.0 {
|
||||
if let Ok((mut direction, transform)) = query.get_mut(event.0) {
|
||||
if let Some((x, y, new_direction)) = snake_path.pick(transform) {
|
||||
trace!(
|
||||
"change direction for {:?} in ({:?}, {:?}) to {:?}",
|
||||
event.0, x, y, new_direction
|
||||
);
|
||||
pub fn tail_observer(event: On<GridBarier>, mut query: Query<(&mut Direction, &Transform)>, snake_path: Res<SnakePath>) {
|
||||
let entity = event.entity;
|
||||
if event.observer() == entity {
|
||||
if let Ok((mut direction, transform)) = query.get_mut(event.entity) {
|
||||
if let Some((position, new_direction)) = snake_path.pick(transform) {
|
||||
trace!("change direction for {entity:?} in {position:?} to {new_direction:?}");
|
||||
*direction = new_direction;
|
||||
}
|
||||
}
|
||||
@@ -23,33 +17,28 @@ pub fn tail_observer(
|
||||
}
|
||||
|
||||
/// Слушатель событий [GridBarier] для конца змеи, обновляющий направление его движения из ресурса [SnakePath] и удаляющий полученные значения из [SnakePath]
|
||||
pub fn cleanup_snake_path(
|
||||
event: On<GridBarier>,
|
||||
mut commands: Commands,
|
||||
query: Query<&Transform, With<End>>,
|
||||
) {
|
||||
if let Ok(transform) = query.get(event.0) {
|
||||
pub fn cleanup_snake_path(event: On<GridBarier>, mut commands: Commands, query: Query<&Transform, With<End>>) {
|
||||
if let Ok(transform) = query.get(event.entity) {
|
||||
// trace!("schedule cleaning SnakePath for {:?}", transform);
|
||||
let transform = transform.clone();
|
||||
commands.queue(move |world: &mut World| {
|
||||
let mut snake_path = world.resource_mut::<SnakePath>();
|
||||
if let Some((x, y, dir)) = snake_path.drop(&transform) {
|
||||
trace!(
|
||||
"removed entry from SnakePath: ({:?}, {:?}) => {:?}\n\tsnake_path: {:?}",
|
||||
x, y, dir, *snake_path
|
||||
);
|
||||
if let Some((pos, dir)) = snake_path.drop(&transform) {
|
||||
let map = snake_path.debug();
|
||||
trace!("removed entry from SnakePath: {pos:?} => {dir:?}\n\tsnake_path: {map:?}");
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/// Запланировать установку скорости движения [Velocity] при следующем событии [GridBarier]
|
||||
pub fn schedule_set_velocity(tail: Entity) -> impl Fn(On<GridBarier>, Commands) {
|
||||
move |event: On<GridBarier>, mut commands: Commands| {
|
||||
commands
|
||||
.entity(tail)
|
||||
.entry::<Velocity>()
|
||||
.and_modify(|mut velocity| velocity.0 = SNAKE_VELOCITY as f32);
|
||||
commands.entity(event.observer()).despawn();
|
||||
pub fn schedule_set_velocity(tail: Entity) -> impl Fn(On<GridBarier>, Commands, Query<(&mut Velocity, &Transform)>) {
|
||||
move |event: On<GridBarier>, mut commands: Commands, mut query: Query<(&mut Velocity, &Transform)>| {
|
||||
if let Ok((mut velocity, transform)) = query.get_mut(tail) {
|
||||
if event.dst_pos != transform.into() {
|
||||
velocity.0 = SNAKE_VELOCITY as f32;
|
||||
commands.entity(event.observer()).despawn();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+12
-17
@@ -1,7 +1,7 @@
|
||||
use bevy::prelude::*;
|
||||
|
||||
use crate::{
|
||||
domain::{End, SnakePath, Tail},
|
||||
domain::{End, GridBarier, SnakePath, Tail},
|
||||
observers::{cleanup_snake_path, schedule_set_velocity, tail_observer},
|
||||
};
|
||||
|
||||
@@ -20,16 +20,20 @@ fn spawn_snake(commands: &mut Commands) {
|
||||
commands.insert_resource(SnakePath::default());
|
||||
commands.spawn(Observer::new(cleanup_snake_path));
|
||||
|
||||
commands.spawn(Observer::new(|e: On<GridBarier>| {
|
||||
let entity = e.entity;
|
||||
let src = e.src_pos;
|
||||
let dst = e.dst_pos;
|
||||
trace!("...<{entity:?}> moving {src:>16} => {dst:>16}");
|
||||
}));
|
||||
|
||||
let head = commands
|
||||
.spawn((
|
||||
Head,
|
||||
Direction::default(),
|
||||
Inert::default(),
|
||||
Velocity(SNAKE_VELOCITY as f32),
|
||||
Sprite::from_color(
|
||||
Color::srgb(1., 1., 1.),
|
||||
vec2(HEAD_SIZE as f32, HEAD_SIZE as f32),
|
||||
),
|
||||
Sprite::from_color(Color::srgb(1., 1., 1.), vec2(HEAD_SIZE as f32, HEAD_SIZE as f32)),
|
||||
Transform {
|
||||
translation: vec3(0.0, 0.0, 1.0),
|
||||
..Default::default()
|
||||
@@ -37,10 +41,7 @@ fn spawn_snake(commands: &mut Commands) {
|
||||
))
|
||||
.id();
|
||||
commands.spawn((
|
||||
Sprite::from_color(
|
||||
Color::srgb(1., 0., 0.),
|
||||
vec2(HEAD_SIZE as f32 * 0.3, HEAD_SIZE as f32 * 0.3),
|
||||
),
|
||||
Sprite::from_color(Color::srgb(1., 0., 0.), vec2(HEAD_SIZE as f32 * 0.3, HEAD_SIZE as f32 * 0.3)),
|
||||
Transform {
|
||||
translation: vec3(HEAD_SIZE as f32 * -0.25, HEAD_SIZE as f32 * 0.25, 1.0),
|
||||
..Default::default()
|
||||
@@ -48,10 +49,7 @@ fn spawn_snake(commands: &mut Commands) {
|
||||
ChildOf(head),
|
||||
));
|
||||
commands.spawn((
|
||||
Sprite::from_color(
|
||||
Color::srgb(0., 0., 1.),
|
||||
vec2(HEAD_SIZE as f32 * 0.2, HEAD_SIZE as f32 * 0.2),
|
||||
),
|
||||
Sprite::from_color(Color::srgb(0., 0., 1.), vec2(HEAD_SIZE as f32 * 0.2, HEAD_SIZE as f32 * 0.2)),
|
||||
Transform {
|
||||
translation: vec3(HEAD_SIZE as f32 * 0.25, HEAD_SIZE as f32 * 0.25, 1.0),
|
||||
..Default::default()
|
||||
@@ -66,10 +64,7 @@ fn spawn_snake(commands: &mut Commands) {
|
||||
Direction::default(),
|
||||
Inert::default(),
|
||||
Velocity(0.0),
|
||||
Sprite::from_color(
|
||||
Color::srgb(0.7, 0.7, 0.7),
|
||||
vec2(HEAD_SIZE as f32 * 0.8, HEAD_SIZE as f32 * 0.8),
|
||||
),
|
||||
Sprite::from_color(Color::srgb(0.7, 0.7, 0.7), vec2(HEAD_SIZE as f32 * 0.8, HEAD_SIZE as f32 * 0.8)),
|
||||
Transform {
|
||||
translation: vec3(0.0, 0.0, 0.0),
|
||||
..Default::default()
|
||||
|
||||
+22
-48
@@ -13,12 +13,7 @@ pub fn define_log_layer() -> Option<bevy::log::BoxedFmtLayer> {
|
||||
.with_line_number(false)
|
||||
.with_filter(targets.clone())
|
||||
.boxed();
|
||||
let file = match File::options()
|
||||
.write(true)
|
||||
.create(true)
|
||||
.append(true)
|
||||
.open("snake-game.log")
|
||||
{
|
||||
let file = match File::options().write(true).create(true).append(true).open("snake-game.log") {
|
||||
Ok(file) => file,
|
||||
Err(e) => {
|
||||
eprintln!("No access to log file: {:?}", e);
|
||||
@@ -54,9 +49,9 @@ pub fn split_by_grid(src: f32, dst: f32, grid: f32) -> Vec<(f32, f32)> {
|
||||
let mut src: f32 = src;
|
||||
for step in old_grid_right as i32..new_grid_right as i32 {
|
||||
let step = step as f32 * grid;
|
||||
if step != src {
|
||||
output.push((step, step - src));
|
||||
}
|
||||
// if step != src {
|
||||
output.push((step, step - src));
|
||||
// }
|
||||
src = step;
|
||||
}
|
||||
output.push((dst, dst - src));
|
||||
@@ -64,9 +59,9 @@ pub fn split_by_grid(src: f32, dst: f32, grid: f32) -> Vec<(f32, f32)> {
|
||||
let mut dst: f32 = dst;
|
||||
for step in new_grid_right as i32..old_grid_right as i32 {
|
||||
let step = step as f32 * grid;
|
||||
if step != dst {
|
||||
output.push((dst, dst - step));
|
||||
}
|
||||
// if step != dst {
|
||||
output.push((dst, dst - step));
|
||||
// }
|
||||
dst = step;
|
||||
}
|
||||
output.push((dst, dst - src));
|
||||
@@ -86,53 +81,32 @@ mod test {
|
||||
assert_eq!(split_by_grid(3.0, 5.0, 5.0), vec![(5.0, 2.0)]);
|
||||
assert_eq!(split_by_grid(3.0, 6.0, 5.0), vec![(5.0, 2.0), (6.0, 1.0)]);
|
||||
assert_eq!(split_by_grid(3.0, 10.0, 5.0), vec![(5.0, 2.0), (10.0, 5.0)]);
|
||||
assert_eq!(
|
||||
split_by_grid(3.0, 11.0, 5.0),
|
||||
vec![(5.0, 2.0), (10.0, 5.0), (11.0, 1.0)]
|
||||
);
|
||||
assert_eq!(split_by_grid(3.0, 11.0, 5.0), vec![(5.0, 2.0), (10.0, 5.0), (11.0, 1.0)]);
|
||||
assert_eq!(split_by_grid(-2.0, 3.0, 5.0), vec![(0.0, 2.0), (3.0, 3.0)]);
|
||||
assert_eq!(
|
||||
split_by_grid(-6.0, 7.0, 5.0),
|
||||
vec![(-5.0, 1.0), (0.0, 5.0), (5.0, 5.0), (7.0, 2.0)]
|
||||
);
|
||||
assert_eq!(
|
||||
split_by_grid(-6.0, -2.0, 5.0),
|
||||
vec![(-5.0, 1.0), (-2.0, 3.0)]
|
||||
);
|
||||
assert_eq!(split_by_grid(-6.0, 7.0, 5.0), vec![(-5.0, 1.0), (0.0, 5.0), (5.0, 5.0), (7.0, 2.0)]);
|
||||
assert_eq!(split_by_grid(-6.0, -2.0, 5.0), vec![(-5.0, 1.0), (-2.0, 3.0)]);
|
||||
|
||||
// движение влево
|
||||
assert_eq!(split_by_grid(4.0, 1.0, 5.0), vec![(1.0, -3.0)]);
|
||||
assert_eq!(split_by_grid(5.0, 3.0, 5.0), vec![(3.0, -2.0)]);
|
||||
assert_eq!(split_by_grid(6.0, 3.0, 5.0), vec![(5.0, -1.0), (3.0, -2.0)]);
|
||||
assert_eq!(
|
||||
split_by_grid(10.0, 3.0, 5.0),
|
||||
vec![(5.0, -5.0), (3.0, -2.0)]
|
||||
);
|
||||
assert_eq!(
|
||||
split_by_grid(11.0, 3.0, 5.0),
|
||||
vec![(10.0, -1.0), (5.0, -5.0), (3.0, -2.0)]
|
||||
);
|
||||
assert_eq!(
|
||||
split_by_grid(3.0, -2.0, 5.0),
|
||||
vec![(0.0, -3.0), (-2.0, -2.0)]
|
||||
);
|
||||
assert_eq!(
|
||||
split_by_grid(7.0, -6.0, 5.0),
|
||||
vec![(5.0, -2.0), (0.0, -5.0), (-5.0, -5.0), (-6.0, -1.0)]
|
||||
);
|
||||
assert_eq!(
|
||||
split_by_grid(-2.0, -6.0, 5.0),
|
||||
vec![(-5.0, -3.0), (-6.0, -1.0)]
|
||||
);
|
||||
assert_eq!(split_by_grid(10.0, 3.0, 5.0), vec![(5.0, -5.0), (3.0, -2.0)]);
|
||||
assert_eq!(split_by_grid(11.0, 3.0, 5.0), vec![(10.0, -1.0), (5.0, -5.0), (3.0, -2.0)]);
|
||||
assert_eq!(split_by_grid(3.0, -2.0, 5.0), vec![(0.0, -3.0), (-2.0, -2.0)]);
|
||||
assert_eq!(split_by_grid(7.0, -6.0, 5.0), vec![(5.0, -2.0), (0.0, -5.0), (-5.0, -5.0), (-6.0, -1.0)]);
|
||||
assert_eq!(split_by_grid(-2.0, -6.0, 5.0), vec![(-5.0, -3.0), (-6.0, -1.0)]);
|
||||
|
||||
// сценарии с нулевой сеткой
|
||||
assert_eq!(split_by_grid(1.0, 4.0, 0.0), vec![(4.0, 3.0)]);
|
||||
assert_eq!(split_by_grid(4.0, 1.0, 0.0), vec![(1.0, -3.0)]);
|
||||
|
||||
// Сценарии со стартом в узле сетки
|
||||
assert_eq!(split_by_grid(0.0, 1.5, 5.0), vec![(1.5, 1.5)]);
|
||||
assert_eq!(split_by_grid(5.0, 7.0, 5.0), vec![(7.0, 2.0)]);
|
||||
assert_eq!(split_by_grid(0.0, -1.5, 5.0), vec![(-1.5, -1.5)]);
|
||||
assert_eq!(split_by_grid(5.0, 3.0, 5.0), vec![(3.0, -2.0)]);
|
||||
assert_eq!(split_by_grid(0.0, 1.5, 5.0), vec![(0.0, 0.0), (1.5, 1.5)]);
|
||||
assert_eq!(split_by_grid(5.0, 7.0, 5.0), vec![(5.0, 0.0), (7.0, 2.0)]);
|
||||
assert_eq!(split_by_grid(0.0, -1.5, 5.0), vec![(0.0, 0.0), (-1.5, -1.5)]);
|
||||
assert_eq!(split_by_grid(5.0, 3.0, 5.0), vec![(5.0, 0.0), (3.0, -2.0)]);
|
||||
}
|
||||
}
|
||||
|
||||
mod position;
|
||||
pub use position::Position;
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
use std::{fmt::Display, ops::Deref};
|
||||
|
||||
use bevy::transform::components::Transform;
|
||||
|
||||
use crate::domain::GRID_SIZE;
|
||||
|
||||
#[derive(Clone, Copy, Default, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub struct Position {
|
||||
pub x: i8,
|
||||
pub y: i8,
|
||||
}
|
||||
|
||||
impl Position {
|
||||
pub fn new(x: i8, y: i8) -> Self {
|
||||
Self { x, y }
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Position {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "(x:{}, y:{})", self.x, self.y)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Deref<Target = Transform>> From<T> for Position {
|
||||
fn from(value: T) -> Self {
|
||||
Self {
|
||||
x: (value.translation.x / GRID_SIZE as f32) as i8,
|
||||
y: (value.translation.y / GRID_SIZE as f32) as i8,
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user