more tests for reflection

This commit is contained in:
Thilo Behnke
2022-04-23 12:01:55 +02:00
parent d91b88eb62
commit cf170d40e7
7 changed files with 107 additions and 22 deletions

View File

@@ -66,4 +66,18 @@ pub mod collision {
#[derive(Debug, Eq, PartialEq)]
pub struct Collision(pub u16, pub u16);
pub struct CollisionHandler {}
impl CollisionHandler {
pub fn new() -> CollisionHandler {
CollisionHandler {}
}
pub fn handle(&self, obj_a: &mut GameObject, obj_b: &GameObject) {
if obj_a.is_static {
return;
}
obj_a.vel.reflect(&obj_b.orientation)
}
}
}

View File

@@ -1,5 +1,5 @@
use std::f64::consts::{FRAC_PI_2, FRAC_PI_4};
use crate::collision::collision::{Collision, CollisionDetector, CollisionRegistry, Collisions};
use crate::collision::collision::{Collision, CollisionDetector, CollisionHandler, CollisionRegistry, Collisions};
use crate::game_object::game_object::{GameObject, Shape};
use crate::geom::geom::Vector;
@@ -118,6 +118,7 @@ impl Field {
.collect::<Vec<GameObject>>()
);
let collision_detector = CollisionDetector::new();
let collision_handler = CollisionHandler::new();
self.collisions = collision_detector.detect_collisions(objs.iter().collect());
for ball in self.balls.iter_mut() {
@@ -132,19 +133,20 @@ impl Field {
collision => objs.iter().find(|o| o.id == collision.0).unwrap(),
};
if other.vel == Vector::zero() {
let dot = ball.obj.vel.dot(&other.orientation);
if dot >= - 0.000001 && dot <= 0.000001 {
ball.obj.vel.invert();
} else {
let angle = ball.obj.vel.angle(&other.orientation);
ball.obj.vel.rotate(FRAC_PI_2 - angle);
ball.obj.vel.invert();
}
} else {
ball.obj.vel.add(&other.vel);
ball.obj.vel.invert();
}
collision_handler.handle(&mut ball.obj, other);
// if other.vel == Vector::zero() {
// let dot = ball.obj.vel.dot(&other.orientation);
// if dot >= - 0.000001 && dot <= 0.000001 {
// ball.obj.vel.invert();
// } else {
// let angle = ball.obj.vel.angle(&other.orientation);
// ball.obj.vel.rotate(FRAC_PI_2 - angle);
// ball.obj.vel.invert();
// }
// } else {
// ball.obj.vel.add(&other.vel);
// ball.obj.vel.invert();
// }
}
}

View File

@@ -80,6 +80,12 @@ pub mod geom {
(acos_res * 100.0).round() / 100.0
}
pub fn reflect(&mut self, onto: &Vector) {
let mut orthogonal = self.get_opposing_orthogonal(onto);
orthogonal.scalar_multiplication(2.);
self.add(&orthogonal);
}
pub fn get_projection(&self, onto: &Vector) -> Vector {
let mut onto_normalized = onto.clone();
onto_normalized.normalize();

View File

@@ -0,0 +1,49 @@
use rstest::rstest;
use pong::collision::collision::CollisionHandler;
use pong::game_object::game_object::{GameObject, Shape};
use pong::geom::geom::Vector;
#[rstest]
#[case(
// given
GameObject {id: 1, pos: Vector::zero(), vel: Vector::new(1., 0.), shape: Shape::Rect, shape_params: vec![], is_static: true, orientation: Vector::new(1., 0.)},
GameObject {id: 1, pos: Vector::zero(), vel: Vector::new(0., 1.), shape: Shape::Rect, shape_params: vec![], is_static: true, orientation: Vector::new(0., 1.)},
// expected
GameObject {id: 1, pos: Vector::zero(), vel: Vector::new(1., 0.), shape: Shape::Rect, shape_params: vec![], is_static: true, orientation: Vector::new(1., 0.)},
GameObject {id: 1, pos: Vector::zero(), vel: Vector::new(0., 1.), shape: Shape::Rect, shape_params: vec![], is_static: true, orientation: Vector::new(0., 1.)},
)]
#[case(
// given
GameObject {id: 1, pos: Vector::zero(), vel: Vector::new(1., 0.), shape: Shape::Rect, shape_params: vec![], is_static: false, orientation: Vector::new(1., 0.)},
GameObject {id: 1, pos: Vector::zero(), vel: Vector::new(0., 1.), shape: Shape::Rect, shape_params: vec![], is_static: true, orientation: Vector::new(0., 1.)},
// expected
GameObject {id: 1, pos: Vector::zero(), vel: Vector::new(-1., 0.), shape: Shape::Rect, shape_params: vec![], is_static: false, orientation: Vector::new(1., 0.)},
GameObject {id: 1, pos: Vector::zero(), vel: Vector::new(0., 1.), shape: Shape::Rect, shape_params: vec![], is_static: true, orientation: Vector::new(0., 1.)},
)]
#[case(
// given
GameObject {id: 1, pos: Vector::zero(), vel: Vector::new(-1., 0.), shape: Shape::Rect, shape_params: vec![], is_static: false, orientation: Vector::new(-1., 0.)},
GameObject {id: 1, pos: Vector::zero(), vel: Vector::new(0., 1.), shape: Shape::Rect, shape_params: vec![], is_static: true, orientation: Vector::new(0., 1.)},
// expected
GameObject {id: 1, pos: Vector::zero(), vel: Vector::new(1., 0.), shape: Shape::Rect, shape_params: vec![], is_static: false, orientation: Vector::new(-1., 0.)},
GameObject {id: 1, pos: Vector::zero(), vel: Vector::new(0., 1.), shape: Shape::Rect, shape_params: vec![], is_static: true, orientation: Vector::new(0., 1.)},
)]
#[case(
// given
GameObject {id: 1, pos: Vector::zero(), vel: Vector::new(1., 1.), shape: Shape::Rect, shape_params: vec![], is_static: false, orientation: Vector::new(1., 1.)},
GameObject {id: 1, pos: Vector::zero(), vel: Vector::new(0., 1.), shape: Shape::Rect, shape_params: vec![], is_static: true, orientation: Vector::new(0., 1.)},
// expected
GameObject {id: 1, pos: Vector::zero(), vel: Vector::new(-1., 1.), shape: Shape::Rect, shape_params: vec![], is_static: false, orientation: Vector::new(1., 1.)},
GameObject {id: 1, pos: Vector::zero(), vel: Vector::new(0., 1.), shape: Shape::Rect, shape_params: vec![], is_static: true, orientation: Vector::new(0., 1.)},
)]
pub fn should_handle_collision(
#[case] mut obj_a: GameObject,
#[case] obj_b: GameObject,
#[case] expected_a: GameObject,
#[case] expected_b: GameObject,
) {
let handler = CollisionHandler {};
handler.handle(&mut obj_a, &obj_b);
assert_eq!(obj_a, expected_a);
assert_eq!(obj_b, expected_b);
}

View File

@@ -7,29 +7,29 @@ use pong::geom::geom::{Vector};
#[case(vec![], vec![])]
#[case(
vec![
GameObject{id: 1, pos: Vector{x: 50., y: 50.}, shape: Shape::Rect, shape_params: vec![20, 20], vel: Vector::zero(), is_static: false},
GameObject{id: 2, pos: Vector{x: 50., y: 50.}, shape: Shape::Rect, shape_params: vec![20, 20], vel: Vector::zero(), is_static: false}
GameObject{id: 1, pos: Vector{x: 50., y: 50.}, shape: Shape::Rect, shape_params: vec![20, 20], vel: Vector::zero(), is_static: false, orientation: Vector::new(1., 1.)},
GameObject{id: 2, pos: Vector{x: 50., y: 50.}, shape: Shape::Rect, shape_params: vec![20, 20], vel: Vector::zero(), is_static: false, orientation: Vector::new(1., 1.)}
],
vec![Collision(1, 2)]
)]
#[case(
vec![
GameObject{id: 1, pos: Vector{x: 60., y: 65.}, shape: Shape::Rect, shape_params: vec![20, 20], vel: Vector::zero(), is_static: false},
GameObject{id: 2, pos: Vector{x: 50., y: 50.}, shape: Shape::Rect, shape_params: vec![20, 20], vel: Vector::zero(), is_static: false}
GameObject{id: 1, pos: Vector{x: 60., y: 65.}, shape: Shape::Rect, shape_params: vec![20, 20], vel: Vector::zero(), is_static: false, orientation: Vector::new(1., 1.)},
GameObject{id: 2, pos: Vector{x: 50., y: 50.}, shape: Shape::Rect, shape_params: vec![20, 20], vel: Vector::zero(), is_static: false, orientation: Vector::new(1., 1.)}
],
vec![Collision(1, 2)]
)]
#[case(
vec![
GameObject{id: 1, pos: Vector{x: 50., y: 50.}, shape: Shape::Rect, shape_params: vec![20, 20], vel: Vector::zero(), is_static: false},
GameObject{id: 2, pos: Vector{x: 80., y: 80.}, shape: Shape::Rect, shape_params: vec![20, 20], vel: Vector::zero(), is_static: false}
GameObject{id: 1, pos: Vector{x: 50., y: 50.}, shape: Shape::Rect, shape_params: vec![20, 20], vel: Vector::zero(), is_static: false, orientation: Vector::new(1., 1.)},
GameObject{id: 2, pos: Vector{x: 80., y: 80.}, shape: Shape::Rect, shape_params: vec![20, 20], vel: Vector::zero(), is_static: false, orientation: Vector::new(1., 1.)}
],
vec![]
)]
#[case(
vec![
GameObject{id: 1, pos: Vector{x: 50., y: 50.}, shape: Shape::Rect, shape_params: vec![50, 50], vel: Vector::zero(), is_static: false},
GameObject{id: 2, pos: Vector{x: 500., y: 50.}, shape: Shape::Rect, shape_params: vec![50, 50], vel: Vector::zero(), is_static: false}
GameObject{id: 1, pos: Vector{x: 50., y: 50.}, shape: Shape::Rect, shape_params: vec![50, 50], vel: Vector::zero(), is_static: false, orientation: Vector::new(1., 1.)},
GameObject{id: 2, pos: Vector{x: 500., y: 50.}, shape: Shape::Rect, shape_params: vec![50, 50], vel: Vector::zero(), is_static: false, orientation: Vector::new(1., 1.)}
],
vec![]
)]

View File

@@ -12,6 +12,7 @@ pub fn should_update_pos(#[case] start_pos: Vector, #[case] vel: Vector, #[case]
shape: Shape::Rect,
shape_params: vec![],
is_static: false,
orientation: Vector::new(1., 0.)
};
obj.update_pos();
assert_eq!(obj.pos, expected_pos);

View File

@@ -121,4 +121,17 @@ pub fn should_get_opposing_orthogonal(
assert_eq!(orthogonal, expected);
}
#[rstest]
#[case(Vector::new(1., 1.), Vector::new(1., 0.), Vector::new(1., -1.))]
#[case(Vector::new(-1., 1.), Vector::new(1., 0.), Vector::new(-1., -1.))]
#[case(Vector::new(1., -1.), Vector::new(0., 1.), Vector::new(-1., -1.))]
#[case(Vector::new(-1., -1.), Vector::new(0., 1.), Vector::new(1., -1.))]
pub fn should_reflect_vector(
#[case] mut vector: Vector,
#[case] onto: Vector,
#[case] expected: Vector,
) {
vector.reflect(&onto);
assert_eq!(vector, expected);
}