use quadtree_rs::{area::AreaBuilder, point::Point, Quadtree};
use crate::geometry::{Rectangle, Vector};
use super::CollisionStrategy;
pub struct BoundingBoxCollider {
qt: Quadtree<u32, Rectangle>,
padding: u32,
}
impl BoundingBoxCollider {
pub fn new(max_width: u32, padding: u32) -> BoundingBoxCollider {
BoundingBoxCollider {
qt: Quadtree::<u32, Rectangle>::new(f32::sqrt(max_width as f32) as usize),
padding,
}
}
}
impl CollisionStrategy for BoundingBoxCollider {
fn collides(&self, pos: Vector, r: &Rectangle) -> bool {
let r = r.grow(2 * self.padding as isize).unwrap();
let region = AreaBuilder::default()
.anchor(Point { x: pos.0, y: pos.1 })
.dimensions((r.size().0, r.size().1))
.build()
.unwrap();
let query = self.qt.query(region);
query.count() != 0
}
fn add(&mut self, pos: Vector, r: Rectangle) {
let region = AreaBuilder::default()
.anchor(Point {
x: pos.0 + self.padding,
y: pos.1 + self.padding,
})
.dimensions((r.size().0, r.size().1))
.build()
.unwrap();
self.qt.insert(region, r);
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn collide() {
let mut bbc = BoundingBoxCollider::new(50, 0);
bbc.add((0, 0), Rectangle::new(0, 0, 10, 5));
bbc.add((20, 0), Rectangle::new(20, 0, 10, 10));
assert!(!bbc.collides((15, 5), &Rectangle::new(0, 0, 5, 3)));
assert!(!bbc.collides((30, 5), &Rectangle::new(0, 0, 5, 3)));
assert!(bbc.collides((15, 0), &Rectangle::new(0, 0, 10, 10)));
assert!(bbc.collides((0, 0), &Rectangle::new(0, 0, 1, 1)));
}
}