use bevy::math::Mat2;
use bevy::prelude::*;
use serde::{Deserialize, Serialize};
use super::{Aabb, Transform2D};
#[derive(Clone, Debug, Serialize, Deserialize, Reflect)]
pub struct Circle {
pub offset: Vec2,
pub radius: f32,
}
impl Circle {
pub fn new(radius: f32) -> Self {
Circle {
offset: Vec2::ZERO,
radius,
}
}
pub fn with_offset(
mut self,
offset: Vec2,
) -> Self {
self.offset = offset;
self
}
pub fn aabb(
&self,
transform: &Transform2D,
) -> Aabb {
let rot = Mat2::from_angle(transform.rotation());
Aabb {
extents: Vec2::splat(self.radius),
position: transform.translation() + rot * self.offset,
}
}
pub fn ray(&self, trans: &Transform2D, ray_origin: Vec2, ray_cast: Vec2) -> Option<f32> {
let n = ray_cast.normalize();
let p = n.perp();
let center = trans.translation() + Mat2::from_angle(trans.rotation()) * self.offset;
let center_n = n.dot(center);
let center_p = p.dot(center);
let ray_n = n.dot(ray_origin);
let ray_p = p.dot(ray_origin);
if (ray_p - center_p).abs() < self.radius {
let dis = (self.radius.powi(2) - (ray_p - center_p).powi(2)).sqrt();
let dis = if center_n - dis < ray_n { center_n + dis } else { center_n - dis } - ray_n;
if n.dot(ray_cast) > dis && dis > 0.0 {
Some(dis / n.dot(ray_cast))
}
else {
None }
}
else {
None }
}
}
impl Default for Circle {
fn default() -> Self {
Self::new(1.0)
}
}