impl Rect {
fn disp(&self, r2:Self) -> Option<(isize,isize)> {
let x_overlap = (self.x+self.w).min(r2.x+r2.w) as isize - self.x.max(r2.x) as isize;
let y_overlap = (self.y+self.h).min(r2.y+r2.h) as isize - self.y.max(r2.y) as isize;
if x_overlap >= 0 && y_overlap >= 0 {
Some((x_overlap, y_overlap))
} else {
None
}
}
}
fn gather_contacts(statics: &[Wall], dynamics:&[Mobile], into:&mut Vec<Contact>) {
for (ai,a) in dynamics.iter().enumerate() {
for (bi,b) in dynamics[(ai+1)..].iter().enumerate() {
if let Some(disp) = rect_displacement(a.rect, b.rect) {
into.push(Contact{a:ColliderID::Dynamic(ai), b:ColliderID::Dynamic(bi), mtv:disp});
}
}
}
for (ai,a) in dynamics.iter().enumerate() {
for (bi,b) in statics.iter().enumerate() {
if let Some(disp) = rect_displacement(a.rect, b.rect) {
into.push(Contact{a:ColliderID::Dynamic(ai), b:ColliderID::Static(bi), mtv:disp});
}
}
}
}
fn restitute(statics: &[Wall], dynamics:&mut [Mobile], contacts:&mut [Contact]) {
contacts.sort_unstable_by_key(|c| -(c.mtv.0*c.mtv.0+c.mtv.1*c.mtv.1));
let mut disps:Vec<(i32,i32)> = dynamics.iter().map(|_| (0,0)).collect();
for c in contacts.iter() {
match (c.a, c.b) {
(ColliderID::Dynamic(_a), ColliderID::Dynamic(_b)) => todo!(),
(ColliderID::Dynamic(a), ColliderID::Static(b)) => {
let mtv = (c.mtv.0 + disps[a].0, c.mtv.1 + disps[a].1);
if mtv.0 == 0 || mtv.1 == 0 { continue; }
if mtv.0 <= mtv.1 {
if statics[b].rect.x+statics[b].rect.w as i32/2 < dynamics[a].rect.x+dynamics[a].rect.w as i32/2 {
disps[a].0 += mtv.0;
dynamics[a].rect.x += mtv.0;
} else {
disps[a].0 -= mtv.0;
dynamics[a].rect.x -= mtv.0;
}
} else {
if statics[b].rect.y+statics[b].rect.h as i32/2 < dynamics[a].rect.y+dynamics[a].rect.h as i32/2 {
disps[a].1 += mtv.1;
dynamics[a].rect.y += mtv.1;
} else {
disps[a].1 -= mtv.1;
dynamics[a].rect.y -= mtv.1;
}
}
},
(ColliderID::Static(_), _) => panic!(),
}
}
}