From 7d412ce6102c89c799eadeab521be3dc6668e849 Mon Sep 17 00:00:00 2001 From: hal8174 Date: Thu, 19 Sep 2024 01:30:44 +0200 Subject: [PATCH] Improve common types --- src/common/aabb.rs | 74 ++++++++++++++++++++++++++++++++++++ src/common/block.rs | 36 ++++++++++++++++++ src/common/mod.rs | 3 ++ src/common/position.rs | 8 ++++ src/common/transformation.rs | 42 ++++++++++++++++++++ src/lib.rs | 9 ++++- 6 files changed, 170 insertions(+), 2 deletions(-) create mode 100644 src/common/aabb.rs create mode 100644 src/common/block.rs create mode 100644 src/common/transformation.rs diff --git a/src/common/aabb.rs b/src/common/aabb.rs new file mode 100644 index 0000000..dcf6d1a --- /dev/null +++ b/src/common/aabb.rs @@ -0,0 +1,74 @@ +use crate::prelude::*; + +/// Axis Aligned Bounding Box +/// The max position is inclusive +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct AABB { + max: Position, + min: Position, +} + +impl AABB { + pub fn new(min: Position, max: Position) -> Self { + Self { min, max } + } + + pub fn combine(self, other: Self) -> Self { + AABB::new( + Position::new( + i32::min(self.min.x, other.min.x), + i32::min(self.min.y, other.min.y), + ), + Position::new( + i32::max(self.max.x, other.max.x), + i32::max(self.max.y, other.max.y), + ), + ) + } + + pub fn min(&self) -> Position { + self.min + } + + pub fn max(&self) -> Position { + self.max + } + + pub fn size(&self) -> Position { + (self.max - self.min) + Position::new(1, 1) + } + + pub fn collision(self, other: Self) -> bool { + self.min.x <= other.max.x + && self.max.x >= other.min.x + && self.min.y <= other.max.y + && self.max.y >= other.min.y + } +} + +#[cfg(test)] +mod test { + use crate::prelude::*; + + #[test] + fn collision() { + let a = AABB::new(Position::new(0, 0), Position::new(8, 8)); + + let b = AABB::new(Position::new(8, 8), Position::new(8, 8)); + assert!(AABB::collision(a, b)); + + let b = AABB::new(Position::new(9, 8), Position::new(9, 8)); + assert!(!AABB::collision(a, b)); + } + + #[test] + fn combine() { + let a = AABB::new(Position::new(9, 0), Position::new(9, 0)); + let b = AABB::new(Position::new(0, 9), Position::new(0, 9)); + + assert_eq!( + AABB::combine(a, b), + AABB::new(Position::new(0, 0), Position::new(9, 9)) + ); + } +} diff --git a/src/common/block.rs b/src/common/block.rs new file mode 100644 index 0000000..2cf014a --- /dev/null +++ b/src/common/block.rs @@ -0,0 +1,36 @@ +use crate::prelude::*; + +#[derive(Clone, Copy, Debug)] +pub struct Block { + pos: Position, + dir: Direction, + size: Position, +} + +impl Block { + pub fn new(size: Position) -> Self { + Self { + pos: Position::new(0, 0), + dir: Direction::Up, + size, + } + } + + pub fn get_aabb(&self) -> AABB { + let npos = match self.dir { + Direction::Up => self.pos, + Direction::Right => self.pos.in_direction(&Direction::Left, self.size.y - 1), + Direction::Down => self.pos - (self.size - Position::new(1, 1)), + Direction::Left => self.pos.in_direction(&Direction::Up, self.size.x - 1), + }; + let nsize = match self.dir { + Direction::Up | Direction::Down => self.size, + Direction::Right | Direction::Left => Position { + x: self.size.y, + y: self.size.x, + }, + }; + + AABB::new(npos, npos + nsize - Position::new(1, 1)) + } +} diff --git a/src/common/mod.rs b/src/common/mod.rs index a4a8298..fb457f6 100644 --- a/src/common/mod.rs +++ b/src/common/mod.rs @@ -1,4 +1,7 @@ +pub mod aabb; +pub mod block; pub mod color; pub mod direction; pub mod position; +pub mod transformation; pub mod visualize; diff --git a/src/common/position.rs b/src/common/position.rs index 66e7f7d..68fc71c 100644 --- a/src/common/position.rs +++ b/src/common/position.rs @@ -1,6 +1,8 @@ use crate::prelude::*; use serde::{Deserialize, Serialize}; +use super::transformation; + pub type PositionType = i32; #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Deserialize, Serialize)] @@ -65,3 +67,9 @@ impl std::ops::Sub for Position { self } } + +impl From<(i32, i32)> for Position { + fn from(value: (i32, i32)) -> Self { + Position::new(value.0, value.1) + } +} diff --git a/src/common/transformation.rs b/src/common/transformation.rs new file mode 100644 index 0000000..cd74aa9 --- /dev/null +++ b/src/common/transformation.rs @@ -0,0 +1,42 @@ +use crate::prelude::*; + +#[derive(Clone, Copy, Debug)] +pub struct Transformation { + rot: Direction, + pos: Position, +} + +impl Transformation { + pub fn new(rot: Direction, pos: Position) -> Self { + Self { rot, pos } + } + + pub fn transform_position(&self, pos: Position) -> Position { + (match self.rot { + Direction::Up => pos, + Direction::Right => Position::new(-pos.y, pos.x), + Direction::Down => Position::new(-pos.x, -pos.y), + Direction::Left => Position::new(pos.y, -pos.x), + }) + self.pos + } + + pub fn rot(&self) -> Direction { + self.rot + } +} + +#[cfg(test)] +mod test { + use crate::prelude::*; + + #[test] + fn position() { + let p = Position::new(3, 5); + + let t = Transformation::new(Direction::Up, Position::new(-3, -5)); + assert_eq!(t.transform_position(p), Position::new(0, 0)); + + let t = Transformation::new(Direction::Down, Position::new(-3, -5)); + assert_eq!(t.transform_position(p), Position::new(-6, -10)); + } +} diff --git a/src/lib.rs b/src/lib.rs index b1f7039..642ca7b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -7,6 +7,11 @@ pub mod misc; pub mod priority_queue; pub mod prelude { - pub use crate::common::direction::Direction; - pub use crate::common::position::{Position, PositionType}; + pub use crate::common::{ + aabb::AABB, + block::Block, + direction::Direction, + position::{Position, PositionType}, + transformation::Transformation, + }; }