use geometry::*; pub enum Hitbox { Circle(CircleHitbox), Point(PointHitbox), Capsule(CapsuleHitbox) } pub struct CircleHitbox { pub pos: Vec2d, pub radius: f64 } pub struct PointHitbox { pub pos: Vec2d } pub struct CapsuleHitbox { pub line: LineSegment, pub radius: f64 } impl Hitbox { pub fn intersect(a: &Hitbox, b: &Hitbox) -> bool { use self::Hitbox::*; match (a, b) { (Circle(x), Circle(y)) => circles_intersect(x, y), (Circle(x), Point(y)) => circle_point_intersect(x, y), (Point(x), Circle(y)) => circle_point_intersect(y, x), (Point(x), Point(y)) => points_intersect(x, y), (Capsule(x), Capsule(y)) => capsules_intersect(x, y), (Capsule(x), Circle(y)) => capsule_circle_intersect(x, y), (Circle(x), Capsule(y)) => capsule_circle_intersect(y, x), (Capsule(x), Point(y)) => capsule_point_intersect(x, y), (Point(x), Capsule(y)) => capsule_point_intersect(y, x), } } } fn circles_intersect(x: &CircleHitbox, y: &CircleHitbox) -> bool { x.pos.distance_squared(y.pos) <= (x.radius + y.radius).powi(2) } fn circle_point_intersect(x: &CircleHitbox, y: &PointHitbox) -> bool { x.pos.distance_squared(y.pos) <= x.radius.powi(2) } fn points_intersect(x: &PointHitbox, y: &PointHitbox) -> bool { x.pos == y.pos } fn capsules_intersect(x: &CapsuleHitbox, y: &CapsuleHitbox) -> bool { true //TODO } fn capsule_circle_intersect(x: &CapsuleHitbox, y: &CircleHitbox) -> bool { x.line.distance(y.pos) <= x.radius + y.radius } fn capsule_point_intersect(x: &CapsuleHitbox, y: &PointHitbox) -> bool { x.line.distance(y.pos) <= x.radius } #[cfg(test)] mod tests { use super::*; #[test] fn circle_intersecting_circle_origin_example() { assert_eq!(Hitbox::intersect( &Hitbox::Circle(CircleHitbox { pos: Vec2d::new(0.,0.), radius: 0. }), &Hitbox::Circle(CircleHitbox { pos: Vec2d::new(0.,0.), radius: 0. }) ), true); } #[test] fn circle_intersecting_circle_origin_elsewhere() { assert_eq!(Hitbox::intersect( &Hitbox::Circle(CircleHitbox { pos: Vec2d::new(0.,0.), radius: 0.5 }), &Hitbox::Circle(CircleHitbox { pos: Vec2d::new(1.,0.), radius: 0.5 }) ), true); } #[test] fn circle_intersecting_circle_origin_outside() { assert_eq!(Hitbox::intersect( &Hitbox::Circle(CircleHitbox { pos: Vec2d::new(0.,0.), radius: 0.5 }), &Hitbox::Circle(CircleHitbox { pos: Vec2d::new(1.,0.), radius: 0.4 }) ), false); } }