mod grid;
mod collider;
mod events;
mod dur_hitbox;
pub use self::collider::*;
use std::f64;
use geom::*;
use geom::shape::PlacedBounds;
use self::dur_hitbox::{DurHitbox, DurHbVel};
const HIGH_TIME: f64 = 1e50;
pub type HbId = u64;
#[derive(PartialEq, Clone, Debug)]
pub struct HbVel {
pub value: Vec2,
pub resize: Vec2,
pub end_time: f64,
}
impl HbVel {
#[inline]
pub fn moving(value: Vec2) -> HbVel {
HbVel { value, resize: Vec2::zero(), end_time: f64::INFINITY }
}
#[inline]
pub fn moving_until(value: Vec2, end_time: f64) -> HbVel {
HbVel { value, resize: Vec2::zero(), end_time }
}
#[inline]
pub fn still() -> HbVel {
HbVel { value: Vec2::zero(), resize: Vec2::zero(), end_time: f64::INFINITY }
}
#[inline]
pub fn still_until(end_time: f64) -> HbVel {
HbVel { value: Vec2::zero(), resize: Vec2::zero(), end_time }
}
}
impl From<Vec2> for HbVel {
fn from(value: Vec2) -> HbVel { HbVel::moving(value) }
}
impl PlacedBounds for HbVel {
fn bounds_center(&self) -> &Vec2 { &self.value }
fn bounds_dims(&self) -> &Vec2 { &self.resize }
}
#[derive(PartialEq, Clone, Debug)]
pub struct Hitbox {
pub value: PlacedShape,
pub vel: HbVel,
}
impl Hitbox {
#[inline]
pub fn new(value: PlacedShape, vel: HbVel) -> Hitbox {
Hitbox { value, vel }
}
fn advanced_shape(&self, time: f64) -> PlacedShape {
assert!(time < HIGH_TIME, "requires time < {}", HIGH_TIME);
self.value.advance(self.vel.value, self.vel.resize, time)
}
fn validate(&self, min_size: f64, present_time: f64) {
assert!(!self.vel.end_time.is_nan() && self.vel.end_time >= present_time, "end time must exceed present time");
if self.value.kind() == ShapeKind::Circle {
assert_eq!(self.vel.resize.x, self.vel.resize.y, "circle resize velocity must maintain aspect ratio");
}
assert!(self.value.dims().x >= min_size && self.value.dims().y >= min_size, "shape width/height must be at least {}", min_size);
}
fn time_until_too_small(&self, min_size: f64) -> f64 {
let min_size = min_size * 0.9;
assert!(self.value.dims().x > min_size && self.value.dims().y > min_size);
let mut time = f64::INFINITY;
if self.vel.resize.x < 0.0 { time = time.min((min_size - self.value.dims().x) / self.vel.value.x); }
if self.vel.resize.y < 0.0 { time = time.min((min_size - self.value.dims().y) / self.vel.value.y); }
time
}
fn to_dur_hitbox(&self, time: f64) -> DurHitbox {
assert!(time <= self.vel.end_time);
DurHitbox {
value: self.value,
vel: DurHbVel {
value: self.vel.value,
resize: self.vel.resize,
duration: self.vel.end_time - time,
},
}
}
}
pub type HbGroup = u32;
static DEFAULT_GROUPS: [HbGroup; 1] = [0];
pub trait HbProfile: Copy {
fn id(&self) -> HbId;
fn group(&self) -> Option<HbGroup> { Some(0) }
fn interact_groups(&self) -> &'static [HbGroup] { &DEFAULT_GROUPS }
fn can_interact(&self, other: &Self) -> bool;
fn cell_width() -> f64;
fn padding() -> f64;
}