diff --git a/tdkpin-rs/src/table.rs b/tdkpin-rs/src/table.rs index 9428983..db84393 100644 --- a/tdkpin-rs/src/table.rs +++ b/tdkpin-rs/src/table.rs @@ -215,6 +215,7 @@ pub const BUMPERS: [StaticCircle; 3] = [ #[cfg(test)] mod tests { use super::*; + use crate::geometry::{circle_collision, segment_collision}; #[test] fn recovered_object_inventory_is_complete() { @@ -238,4 +239,65 @@ mod tests { assert_eq!(shooter_wall.segment.start, Vec2::new(328.0, 422.0)); assert_eq!(shooter_wall.segment.end, Vec2::new(328.0, 58.0)); } + + #[test] + fn every_recovered_wall_has_a_working_contact_surface_on_both_sides() { + for wall in WALLS { + let line = wall.segment.end - wall.segment.start; + assert!( + line.length_squared() > 0.0, + "object {} is degenerate", + wall.id + ); + let normal = Vec2::new(-line.y, line.x).normalize(); + let midpoint = (wall.segment.start + wall.segment.end) * 0.5; + + for side in [-1.0, 1.0] { + let outward = normal * side; + let mut position = midpoint + outward * 0.5; + let mut velocity = -outward * 430.0; + let hit = segment_collision(&mut position, &mut velocity, 1.0, wall.segment); + + assert!(hit, "object {} missed its midpoint contact", wall.id); + assert!( + velocity.dot(outward) >= 0.0, + "object {} did not reject an inward trajectory", + wall.id + ); + assert!( + position.distance(midpoint) >= 0.99, + "object {} did not separate the ball from its surface", + wall.id + ); + } + } + } + + #[test] + fn every_recovered_circle_separates_and_reflects_the_ball() { + for circle in PASSIVE_CIRCLES.iter().chain(BUMPERS.iter()) { + let mut position = circle.center + Vec2::new(circle.contact_radius - 0.5, 0.0); + let mut velocity = Vec2::new(-430.0, 0.0); + let hit = circle_collision( + &mut position, + &mut velocity, + 0.0, + circle.center, + circle.contact_radius, + 0.0, + ); + + assert!(hit, "object {} missed an overlapping ball", circle.id); + assert!( + position.x >= circle.center.x + circle.contact_radius, + "object {} did not separate the ball", + circle.id + ); + assert!( + velocity.x > 0.0, + "object {} did not reflect inward velocity", + circle.id + ); + } + } }