use crate::prelude::*; use serde::{Deserialize, Serialize}; pub type PositionType = i32; #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Deserialize, Serialize)] pub struct Position { pub x: PositionType, pub y: PositionType, } #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] pub struct Dimension { pub width: usize, pub height: usize, } impl Position { pub fn new(x: PositionType, y: PositionType) -> Self { Self { x, y } } pub fn in_direction(&self, dir: &Direction, len: PositionType) -> Position { match dir { Direction::Up => Position::new(self.x, self.y - len), Direction::Right => Position::new(self.x + len, self.y), Direction::Down => Position::new(self.x, self.y + len), Direction::Left => Position::new(self.x - len, self.y), } } pub fn in_range(&self, min: &Position, max: &Position) -> Option<&Position> { if self.x < min.x { return None; } if self.x >= max.x { return None; } if self.y < min.y { return None; } if self.y >= max.y { return None; } Some(self) } } impl std::ops::Add for Position { type Output = Position; fn add(mut self, rhs: Self) -> Self::Output { self.x += rhs.x; self.y += rhs.y; self } } impl std::ops::Sub for Position { type Output = Position; fn sub(mut self, rhs: Self) -> Self::Output { self.x -= rhs.x; self.y -= rhs.y; self } } impl From<(i32, i32)> for Position { fn from(value: (i32, i32)) -> Self { Position::new(value.0, value.1) } }