diff --git a/client/wasm/src/lib.rs b/client/wasm/src/lib.rs index facd64e..0d08bc8 100644 --- a/client/wasm/src/lib.rs +++ b/client/wasm/src/lib.rs @@ -3,7 +3,7 @@ mod utils; use pong::collision::collision::{Collision, CollisionDetector}; use pong::game_field::{Field, Input, InputType}; use pong::game_object::game_object::{DefaultGameObject, GameObject}; -use pong::geom::geom::Vector; +use pong::geom::vector::Vector; use pong::geom::shape::ShapeType; use pong::pong::pong_events::DefaultPongEventWriter; use pong::utils::utils::{DefaultLoggerFactory, Logger}; diff --git a/pong/src/game_field.rs b/pong/src/game_field.rs index 34b9178..41358d6 100644 --- a/pong/src/game_field.rs +++ b/pong/src/game_field.rs @@ -6,8 +6,8 @@ use crate::collision::collision::{ }; use crate::game_object::components::{DefaultGeomComp, DefaultPhysicsComp}; use crate::game_object::game_object::{DefaultGameObject, GameObject}; -use crate::geom::geom::Vector; use crate::geom::shape::{Shape}; +use crate::geom::vector::Vector; use crate::pong::pong_collisions::{ handle_ball_bounds_collision, handle_player_ball_collision, handle_player_bound_collision, }; diff --git a/pong/src/game_object.rs b/pong/src/game_object.rs index d27391d..25565ea 100644 --- a/pong/src/game_object.rs +++ b/pong/src/game_object.rs @@ -1,8 +1,9 @@ pub mod game_object { use crate::game_object::components::{GeomComp, PhysicsComp}; - use crate::geom::geom::{BoundingBox, Vector}; + use crate::geom::geom::{BoundingBox}; use crate::geom::shape::{ShapeType}; use std::fmt::Debug; + use crate::geom::vector::Vector; pub trait GameObject: Debug { fn id(&self) -> u16; @@ -122,12 +123,13 @@ pub mod game_object { } pub mod components { - use crate::geom::geom::{BoundingBox, Vector}; + use crate::geom::geom::{BoundingBox}; use crate::geom::shape::{ get_bounding_box, get_center, get_center_mut, get_orientation, get_orientation_mut, ShapeType, }; use std::fmt::Debug; + use crate::geom::vector::Vector; pub trait GeomComp: Debug { fn shape(&self) -> &ShapeType; diff --git a/pong/src/geom.rs b/pong/src/geom.rs index bb8c515..e3ec230 100644 --- a/pong/src/geom.rs +++ b/pong/src/geom.rs @@ -1,5 +1,5 @@ -pub mod geom { - use serde::Serialize; +pub mod vector { + use serde::{Serialize}; #[derive(Debug, Clone, Serialize)] pub struct Vector { @@ -163,6 +163,144 @@ pub mod geom { } } + #[cfg(test)] + mod tests { + use rstest::rstest; + use std::f64::consts::FRAC_PI_4; + use crate::geom::vector::Vector; + + #[rstest] + #[case(1., 0., 1.)] + #[case(0., 1., 1.)] + #[case(3., 4., 5.)] + pub fn should_get_correct_length(#[case] x: f64, #[case] y: f64, #[case] expected: f64) { + let vector = Vector { x, y }; + let len = vector.len(); + assert_eq!(len, expected); + } + + #[rstest] + #[case(1., 0., 1., 0.)] + #[case(3., 0., 1., 0.)] + #[case(3., 4., 3. / 5., 4. / 5.)] + pub fn should_normalize_correctly( + #[case] x: f64, + #[case] y: f64, + #[case] expected_x: f64, + #[case] expected_y: f64, + ) { + let mut vector = Vector { x, y }; + let expected = Vector { + x: expected_x, + y: expected_y, + }; + vector.normalize(); + assert_eq!(vector, expected); + } + + #[rstest] + #[case(Vector::new(1., 1.), Vector::new(2., 2.), 0.)] + #[case(Vector::new(1., 0.), Vector::new(1., 1.), 0.79)] + pub fn should_calculate_angle_correctly( + #[case] vector_a: Vector, + #[case] vector_b: Vector, + #[case] expected_angle: f64, + ) { + let res = vector_a.angle(&vector_b); + assert_eq!(res, expected_angle); + } + + #[rstest] + #[case(Vector::new(1., 0.), Vector::new(0., -1.))] + #[case(Vector::new(0., 1.), Vector::new(1., 0.))] + #[case(Vector::new(7., 7.), Vector::new(7., -7.))] + pub fn should_get_orthogonal_clockwise(#[case] mut vector: Vector, #[case] expected: Vector) { + vector.orthogonal_clockwise(); + assert_eq!(vector, expected); + } + + #[rstest] + #[case(Vector::new(0., -1.), Vector::new(1., 0.))] + #[case(Vector::new(1., 0.), Vector::new(0., 1.))] + #[case(Vector::new(7., 7.), Vector::new(-7., 7.))] + pub fn should_get_orthogonal_counter_clockwise( + #[case] mut vector: Vector, + #[case] expected: Vector, + ) { + vector.orthogonal_counter_clockwise(); + assert_eq!(vector, expected); + } + + #[rstest] + #[case(Vector::new(1., 0.), FRAC_PI_4, Vector::unit())] + pub fn should_correctly_rotate( + #[case] mut vector: Vector, + #[case] radians: f64, + #[case] expected: Vector, + ) { + vector.rotate(radians); + assert_eq!(vector, expected); + } + + #[rstest] + #[case(Vector::new(1., 0.), Vector::new(1., 0.), 1.)] + #[case(Vector::new(1., 0.), Vector::new(0., 1.), 0.)] + #[case(Vector::new(1., 0.), Vector::new(-1., 0.), -1.)] + pub fn should_calculate_dot_product( + #[case] vector: Vector, + #[case] other: Vector, + #[case] expected: f64, + ) { + let dot = vector.dot(&other); + assert_eq!(dot, expected); + } + + #[rstest] + #[case(Vector::new(0., 1.), Vector::new(1., 0.), Vector::new(0., 0.))] + #[case(Vector::new(1., 0.), Vector::new(1., 0.), Vector::new(1., 0.))] + #[case(Vector::new(-1., 0.), Vector::new(1., 0.), Vector::new(-1., 0.))] + #[case(Vector::new(1., 1.), Vector::new(1., 0.), Vector::new(1., 0.))] + #[case(Vector::new(2., 1.), Vector::new(1., 0.), Vector::new(2., 0.))] + pub fn should_get_projection( + #[case] vector: Vector, + #[case] other: Vector, + #[case] expected: Vector, + ) { + let projected = vector.get_projection(&other); + assert_eq!(projected, expected); + } + + #[rstest] + #[case(Vector::new(1., 1.), Vector::new(1., 0.), Vector::new(0., -1.))] + #[case(Vector::new(-1., -1.), Vector::new(1., 0.), Vector::new(0., 1.))] + pub fn should_get_opposing_orthogonal( + #[case] vector: Vector, + #[case] onto: Vector, + #[case] expected: Vector, + ) { + let orthogonal = vector.get_opposing_orthogonal(&onto); + 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); + } + } +} + +pub mod geom { + use crate::geom::vector::Vector; + #[derive(Clone, Debug)] pub struct BoundingBox { top_left: Vector, @@ -264,8 +402,9 @@ pub mod geom { } pub mod shape { - use crate::geom::geom::{BoundingBox, Vector}; + use crate::geom::geom::{BoundingBox}; use std::fmt::Debug; + use crate::geom::vector::Vector; #[derive(Clone, Debug, PartialEq)] pub enum ShapeType { diff --git a/pong/src/pong.rs b/pong/src/pong.rs index c9c7f30..18b9b94 100644 --- a/pong/src/pong.rs +++ b/pong/src/pong.rs @@ -1,6 +1,6 @@ pub mod pong_collisions { use crate::game_object::game_object::GameObject; - use crate::geom::geom::Vector; + use crate::geom::vector::{Vector}; use crate::geom::shape::ShapeType; use std::cell::{RefCell}; use std::rc::Rc; @@ -81,7 +81,7 @@ pub mod pong_collisions { pub mod pong_events { use crate::event::event::{Event, EventWriter}; - use crate::geom::geom::Vector; + use crate::geom::vector::Vector; use serde::Serialize; #[derive(Serialize)] diff --git a/pong/tests/bounding_box_tests.rs b/pong/tests/bounding_box_tests.rs index 2a9d21f..13225b7 100644 --- a/pong/tests/bounding_box_tests.rs +++ b/pong/tests/bounding_box_tests.rs @@ -1,5 +1,6 @@ -use pong::geom::geom::{BoundingBox, Vector}; +use pong::geom::geom::{BoundingBox}; use rstest::rstest; +use pong::geom::vector::Vector; #[rstest] #[case(BoundingBox::create(&Vector::new(10., 10.), 5., 5.), Vector::new(10., 10.), true)] diff --git a/pong/tests/collision_handler_test.rs b/pong/tests/collision_handler_test.rs index 9de2c0a..1f1eb96 100644 --- a/pong/tests/collision_handler_test.rs +++ b/pong/tests/collision_handler_test.rs @@ -1,7 +1,7 @@ use pong::collision::collision::CollisionHandler; use pong::game_object::components::{DefaultGeomComp, DefaultPhysicsComp}; use pong::game_object::game_object::{DefaultGameObject, GameObject}; -use pong::geom::geom::Vector; +use pong::geom::vector::Vector; use pong::geom::shape::Shape; use pong::utils::utils::DefaultLoggerFactory; use rstest::rstest; diff --git a/pong/tests/collision_tests.rs b/pong/tests/collision_tests.rs index 918db17..d4e31d5 100644 --- a/pong/tests/collision_tests.rs +++ b/pong/tests/collision_tests.rs @@ -1,11 +1,12 @@ use pong::collision::collision::{Collision, CollisionDetector, CollisionGroup}; use pong::game_object::game_object::GameObject; -use pong::geom::geom::{BoundingBox, Vector}; +use pong::geom::geom::{BoundingBox}; use pong::geom::shape::ShapeType; use pong::utils::utils::DefaultLoggerFactory; use rstest::rstest; use std::cell::{RefCell}; use std::rc::Rc; +use pong::geom::vector::Vector; #[rstest] #[case(vec![], vec![])] diff --git a/pong/tests/game_object_tests.rs b/pong/tests/game_object_tests.rs index 8c36919..b8dd47c 100644 --- a/pong/tests/game_object_tests.rs +++ b/pong/tests/game_object_tests.rs @@ -1,6 +1,6 @@ use pong::game_object::components::{DefaultGeomComp, DefaultPhysicsComp}; use pong::game_object::game_object::{DefaultGameObject, GameObject}; -use pong::geom::geom::Vector; +use pong::geom::vector::Vector; use pong::geom::shape::Shape; use rstest::rstest; diff --git a/pong/tests/pong_tests.rs b/pong/tests/pong_tests.rs index 8b10882..44b9a06 100644 --- a/pong/tests/pong_tests.rs +++ b/pong/tests/pong_tests.rs @@ -1,6 +1,6 @@ use pong::game_field::{Bound, Field}; use pong::game_object::game_object::{DefaultGameObject, GameObject}; -use pong::geom::geom::Vector; +use pong::geom::vector::Vector; use pong::pong::pong_collisions::handle_player_bound_collision; use pong::utils::utils::{DefaultLoggerFactory}; use rstest::rstest; @@ -47,7 +47,7 @@ pub fn should_correctly_handle_player_bounds_collision( #[case] player_expected: Rc>>, #[case] bounds_expected: Rc>>, ) { - handle_player_bound_collision(player.clone(), bounds.clone()); + handle_player_bound_collision(&player, &bounds); assert_eq!(player_expected.borrow().pos(), player.borrow().pos()); assert_eq!(bounds_expected.borrow().pos(), bounds.borrow().pos()); } diff --git a/pong/tests/vector_tests.rs b/pong/tests/vector_tests.rs index cbcd157..e69de29 100644 --- a/pong/tests/vector_tests.rs +++ b/pong/tests/vector_tests.rs @@ -1,130 +0,0 @@ -use pong::geom::geom::Vector; -use rstest::rstest; -use std::f64::consts::FRAC_PI_4; - -#[rstest] -#[case(1., 0., 1.)] -#[case(0., 1., 1.)] -#[case(3., 4., 5.)] -pub fn should_get_correct_length(#[case] x: f64, #[case] y: f64, #[case] expected: f64) { - let vector = Vector { x, y }; - let len = vector.len(); - assert_eq!(len, expected); -} - -#[rstest] -#[case(1., 0., 1., 0.)] -#[case(3., 0., 1., 0.)] -#[case(3., 4., 3. / 5., 4. / 5.)] -pub fn should_normalize_correctly( - #[case] x: f64, - #[case] y: f64, - #[case] expected_x: f64, - #[case] expected_y: f64, -) { - let mut vector = Vector { x, y }; - let expected = Vector { - x: expected_x, - y: expected_y, - }; - vector.normalize(); - assert_eq!(vector, expected); -} - -#[rstest] -#[case(Vector::new(1., 1.), Vector::new(2., 2.), 0.)] -#[case(Vector::new(1., 0.), Vector::new(1., 1.), 0.79)] -pub fn should_calculate_angle_correctly( - #[case] vector_a: Vector, - #[case] vector_b: Vector, - #[case] expected_angle: f64, -) { - let res = vector_a.angle(&vector_b); - assert_eq!(res, expected_angle); -} - -#[rstest] -#[case(Vector::new(1., 0.), Vector::new(0., -1.))] -#[case(Vector::new(0., 1.), Vector::new(1., 0.))] -#[case(Vector::new(7., 7.), Vector::new(7., -7.))] -pub fn should_get_orthogonal_clockwise(#[case] mut vector: Vector, #[case] expected: Vector) { - vector.orthogonal_clockwise(); - assert_eq!(vector, expected); -} - -#[rstest] -#[case(Vector::new(0., -1.), Vector::new(1., 0.))] -#[case(Vector::new(1., 0.), Vector::new(0., 1.))] -#[case(Vector::new(7., 7.), Vector::new(-7., 7.))] -pub fn should_get_orthogonal_counter_clockwise( - #[case] mut vector: Vector, - #[case] expected: Vector, -) { - vector.orthogonal_counter_clockwise(); - assert_eq!(vector, expected); -} - -#[rstest] -#[case(Vector::new(1., 0.), FRAC_PI_4, Vector::unit())] -pub fn should_correctly_rotate( - #[case] mut vector: Vector, - #[case] radians: f64, - #[case] expected: Vector, -) { - vector.rotate(radians); - assert_eq!(vector, expected); -} - -#[rstest] -#[case(Vector::new(1., 0.), Vector::new(1., 0.), 1.)] -#[case(Vector::new(1., 0.), Vector::new(0., 1.), 0.)] -#[case(Vector::new(1., 0.), Vector::new(-1., 0.), -1.)] -pub fn should_calculate_dot_product( - #[case] vector: Vector, - #[case] other: Vector, - #[case] expected: f64, -) { - let dot = vector.dot(&other); - assert_eq!(dot, expected); -} - -#[rstest] -#[case(Vector::new(0., 1.), Vector::new(1., 0.), Vector::new(0., 0.))] -#[case(Vector::new(1., 0.), Vector::new(1., 0.), Vector::new(1., 0.))] -#[case(Vector::new(-1., 0.), Vector::new(1., 0.), Vector::new(-1., 0.))] -#[case(Vector::new(1., 1.), Vector::new(1., 0.), Vector::new(1., 0.))] -#[case(Vector::new(2., 1.), Vector::new(1., 0.), Vector::new(2., 0.))] -pub fn should_get_projection( - #[case] vector: Vector, - #[case] other: Vector, - #[case] expected: Vector, -) { - let projected = vector.get_projection(&other); - assert_eq!(projected, expected); -} - -#[rstest] -#[case(Vector::new(1., 1.), Vector::new(1., 0.), Vector::new(0., -1.))] -#[case(Vector::new(-1., -1.), Vector::new(1., 0.), Vector::new(0., 1.))] -pub fn should_get_opposing_orthogonal( - #[case] vector: Vector, - #[case] onto: Vector, - #[case] expected: Vector, -) { - let orthogonal = vector.get_opposing_orthogonal(&onto); - 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); -}