npc_engine_utils/
direction.rs1use serde::Serialize;
7use std::{fmt, marker::PhantomData};
8
9use crate::Coord2D;
10
11pub trait YUpDown {
13 fn up() -> i32;
15 fn down() -> i32;
17}
18
19pub struct YUp;
21impl YUpDown for YUp {
22 fn up() -> i32 {
23 1
24 }
25 fn down() -> i32 {
26 -1
27 }
28}
29
30pub struct YDown;
32impl YUpDown for YDown {
33 fn up() -> i32 {
34 -1
35 }
36 fn down() -> i32 {
37 1
38 }
39}
40
41#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, Serialize)]
46#[serde(rename_all = "kebab-case")]
47pub enum Direction {
48 Up,
49 Down,
50 Left,
51 Right,
52}
53
54impl fmt::Display for Direction {
55 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
56 match self {
57 Direction::Up => write!(f, "Up"),
58 Direction::Down => write!(f, "Down"),
59 Direction::Left => write!(f, "Left"),
60 Direction::Right => write!(f, "Right"),
61 }
62 }
63}
64
65pub struct DirectionConverter<YDir: YUpDown> {
70 _phantom: PhantomData<YDir>,
71}
72impl<YDir: YUpDown> DirectionConverter<YDir> {
73 pub fn apply(direction: Direction, coord: Coord2D) -> Coord2D {
75 let Coord2D { x, y } = coord;
76 let (x, y) = match direction {
77 Direction::Up => (x, y + YDir::up()),
78 Direction::Down => (x, y + YDir::down()),
79 Direction::Left => (x - 1, y),
80 Direction::Right => (x + 1, y),
81 };
82 Coord2D::new(x, y)
83 }
84
85 pub fn from(start: Coord2D, end: Coord2D) -> Direction {
87 let dx = end.x - start.x;
88 let dy = end.y - start.y;
89 match (dx, dy) {
90 (1, _) => Direction::Right,
91 (-1, _) => Direction::Left,
92 (_, 1) => match YDir::up() == 1 {
93 true => Direction::Up,
94 false => Direction::Down,
95 },
96 (_, -1) => match YDir::down() == -1 {
97 true => Direction::Down,
98 false => Direction::Up,
99 },
100 _ => panic!("start and end positions are not next to each others with 4-connectivity"),
101 }
102 }
103}
104
105pub const DIRECTIONS: [Direction; 4] = [
107 Direction::Up,
108 Direction::Right,
109 Direction::Down,
110 Direction::Left,
111];
112pub type DirectionConverterYUp = DirectionConverter<YUp>;
114pub type DirectionConverterYDown = DirectionConverter<YDown>;