#![cfg(feature = "std")] use std::f32::consts; use approx::assert_abs_diff_eq; use glam::Vec2; use rstest::*; use impacted::{CollisionShape, Transform}; #[rstest] #[case(CollisionShape::new_circle(1.0), CollisionShape::new_circle(1.0))] #[case( CollisionShape::new_circle(1.0), CollisionShape::new_circle(1.0).with_transform(Transform::from_translation(Vec2::ZERO)), )] #[case( CollisionShape::new_circle(1.0), CollisionShape::new_circle(1.0).with_transform(Transform::from_angle_translation(2.0, Vec2::ZERO)), )] #[case( CollisionShape::new_circle(1.0), CollisionShape::new_circle(1.0).with_transform(Transform::from_scale_angle_translation(Vec2::splat(2.0), 2.0, Vec2::ZERO)), )] #[case( CollisionShape::new_circle(1.0), CollisionShape::new_circle(1.0).with_transform(Transform::from_translation(Vec2::new(2.0, 0.0))), )] #[case( CollisionShape::new_circle(1.0), CollisionShape::new_circle(1.0).with_transform(Transform::from_translation(Vec2::X * 1.0)), )] #[case( CollisionShape::new_circle(1.0), CollisionShape::new_circle(1.5).with_transform(Transform::from_translation(Vec2::Y * 2.1)), )] #[case( CollisionShape::new_circle(1.0), CollisionShape::new_rectangle(2.0, 2.0).with_transform(Transform::from_translation(Vec2::X * 1.9)), )] #[case( CollisionShape::new_circle(1.0), CollisionShape::new_rectangle(2.0, 2.0).with_transform(Transform::from_angle_translation(consts::FRAC_PI_4, Vec2::X * 2.3)), )] #[case( CollisionShape::new_circle(1.0), CollisionShape::new_segment(Vec2::ZERO, Vec2::X) )] fn collides(#[case] shape1: CollisionShape, #[case] shape2: CollisionShape) { assert!(shape1.is_collided_with(&shape2)); let contact = shape1.contact_with(&shape2); assert!(contact.is_some(), "{contact:?}"); } #[rstest] #[case( CollisionShape::new_circle(1.0), CollisionShape::new_circle(1.0).with_transform(Transform::from_translation(Vec2::X * 2.1)), )] #[case( CollisionShape::new_circle(1.0), CollisionShape::new_circle(1.0).with_transform(Transform::from_translation(Vec2::Y * 2.1)), )] #[case( CollisionShape::new_circle(1.0), CollisionShape::new_rectangle(2.0, 2.0).with_transform(Transform::from_translation(Vec2::X * 2.1)), )] #[case( CollisionShape::new_circle(1.0), CollisionShape::new_rectangle(2.0, 2.0).with_transform(Transform::from_angle_translation(consts::FRAC_PI_4, Vec2::X * 2.5)), )] #[case( CollisionShape::new_circle(1.0), CollisionShape::new_segment(Vec2::X * 2.0, Vec2::X * 3.0), )] fn does_not_collide(#[case] shape1: CollisionShape, #[case] shape2: CollisionShape) { assert!(!shape1.is_collided_with(&shape2)); let contact = shape1.contact_with(&shape2); assert!(contact.is_none(), "{contact:?}"); } #[rstest] #[case( CollisionShape::new_circle(1.0), CollisionShape::new_circle(1.0).with_transform(Transform::from_translation(Vec2::X * 1.95)), Vec2::new(-1.0, 0.0) )] #[case( CollisionShape::new_circle(1.0), CollisionShape::new_circle(1.0).with_transform(Transform::from_translation(Vec2::Y * 1.95)), Vec2::new(0.0, -1.0) )] #[case( CollisionShape::new_rectangle(1.0, 1.0), CollisionShape::new_rectangle(1.0, 1.0).with_transform(Transform::from_translation(Vec2::X * -0.95)), Vec2::new(1.0, 0.0) )] #[case( CollisionShape::new_rectangle(2.0, 2.0), CollisionShape::new_rectangle(2.0, 2.0).with_transform(Transform::from_angle_translation(consts::FRAC_PI_4 + 0.1, Vec2::X * 2.3)), Vec2::new(-1.0, 0.0) )] #[case( CollisionShape::new_rectangle(2.0, 2.0).with_transform(Transform::from_angle_translation(consts::FRAC_PI_4 + 0.1, Vec2::X * 2.3)), CollisionShape::new_rectangle(2.0, 2.0), Vec2::new(1.0, 0.0) )] fn contact_normal( #[case] shape1: CollisionShape, #[case] shape2: CollisionShape, #[case] expected_normal: Vec2, ) { let contact = shape1.contact_with(&shape2).unwrap(); assert_abs_diff_eq!(Vec2::from(contact.normal), expected_normal, epsilon = 0.001); } #[rstest] #[case( CollisionShape::new_circle(1.0), CollisionShape::new_circle(1.0).with_transform(Transform::from_translation(Vec2::X * 1.95)), 0.05 )] #[case( CollisionShape::new_circle(1.0), CollisionShape::new_circle(1.0).with_transform(Transform::from_translation(Vec2::Y * 1.0)), 1.0 )] #[case( CollisionShape::new_rectangle(1.0, 1.0), CollisionShape::new_rectangle(1.0, 1.0).with_transform(Transform::from_translation(Vec2::X * -0.95)), 0.05 )] #[case( CollisionShape::new_rectangle(1.0, 1.0), CollisionShape::new_rectangle(1.0, 1.0).with_transform(Transform::from_translation(Vec2::X * -0.5)), 0.5 )] #[case( CollisionShape::new_rectangle(2.0, 2.0), CollisionShape::new_rectangle(2.0, 2.0).with_transform(Transform::from_angle_translation(consts::FRAC_PI_4, Vec2::X * 2.3)), 0.1142 )] fn contact_penetration( #[case] shape1: CollisionShape, #[case] shape2: CollisionShape, #[case] expected_penetration: f32, ) { let contact = shape1.contact_with(&shape2).unwrap(); assert_abs_diff_eq!(contact.penetration, expected_penetration, epsilon = 0.0001); }