diff --git a/pong/src/game_field.rs b/pong/src/game_field.rs
index 5bff345..1efbdd0 100644
--- a/pong/src/game_field.rs
+++ b/pong/src/game_field.rs
@@ -1,6 +1,5 @@
-use std::f64::consts::{FRAC_PI_2, FRAC_PI_4};
use crate::collision::collision::{Collision, CollisionDetector, CollisionHandler, CollisionRegistry, Collisions};
-use crate::game_object::game_object::{GameObject, Shape};
+use crate::game_object::game_object::{GameObject, ShapeType};
use crate::geom::geom::Vector;
use crate::utils::utils::{Logger, NoopLogger};
@@ -71,7 +70,7 @@ impl Field {
pub fn tick(&mut self, inputs: Vec) {
for ball in self.balls.iter_mut() {
- if ball.obj.vel == Vector::zero() {
+ if ball.obj.physics.vel() == Vector::zero() {
ball.obj.set_vel_x(-2.)
}
}
@@ -85,10 +84,12 @@ impl Field {
let input = input_opt.unwrap();
match input.input {
InputType::UP => {
- player.obj.vel.y = (player.obj.vel.y + 1.).min(5.);
+ let updated_vel_y = (player.obj.vel.y + 1.).min(5.);
+ player.obj.set_vel_y(updated_vel_y);
}
InputType::DOWN => {
- player.obj.vel.y = (player.obj.vel.y - 1.).max(-5.);
+ let updated_vel_y = (player.obj.vel.y - 1.).max(-5.);
+ player.obj.set_vel_y(updated_vel_y);
}
};
}
@@ -170,7 +171,7 @@ impl Player {
id,
pos: Vector {x: x as f64, y: y as f64},
orientation: Vector::new(0., 1.),
- shape: Shape::Rect,
+ shape: ShapeType::Rect,
shape_params: vec![field.width / 25, field.height / 5],
vel: Vector::zero(),
is_static: true,
@@ -191,7 +192,7 @@ impl Ball {
id,
pos: Vector {x: x as f64, y: y as f64},
orientation: Vector::zero(),
- shape: Shape::Circle,
+ shape: ShapeType::Circle,
shape_params: vec![field.width / 80],
vel: Vector::zero(),
is_static: false,
@@ -214,7 +215,7 @@ impl Bounds {
id: 90,
pos: Vector {x: (width / 2) as f64, y: 0 as f64},
orientation: Vector::new(1., 0.),
- shape: Shape::Rect,
+ shape: ShapeType::Rect,
shape_params: vec![width, 2],
is_static: true,
vel: Vector::zero(),
@@ -224,7 +225,7 @@ impl Bounds {
id: 91,
pos: Vector {x: (width / 2) as f64, y: height as f64},
orientation: Vector::new(-1., 0.),
- shape: Shape::Rect,
+ shape: ShapeType::Rect,
shape_params: vec![width, 2],
is_static: true,
vel: Vector::zero(),
@@ -234,7 +235,7 @@ impl Bounds {
id: 92,
pos: Vector {x: 0 as f64, y: (height / 2) as f64},
orientation: Vector::new(0., 1.),
- shape: Shape::Rect,
+ shape: ShapeType::Rect,
shape_params: vec![2, height],
is_static: true,
vel: Vector::zero(),
@@ -244,7 +245,7 @@ impl Bounds {
id: 93,
pos: Vector {x: width as f64, y: (height / 2) as f64},
orientation: Vector::new(0., -1.),
- shape: Shape::Rect,
+ shape: ShapeType::Rect,
shape_params: vec![2, height],
is_static: true,
vel: Vector::zero(),
diff --git a/pong/src/game_object.rs b/pong/src/game_object.rs
index abae1ec..4454d20 100644
--- a/pong/src/game_object.rs
+++ b/pong/src/game_object.rs
@@ -1,53 +1,108 @@
pub mod game_object {
+ use crate::game_object::components::{GeomComp, PhysicsComp};
use crate::geom::geom::{BoundingBox, Vector};
-
- #[derive(Clone, Debug, PartialEq)]
- pub enum Shape {
- Rect = 0,
- Circle = 1,
- }
+ use crate::geom::shape::ShapeType;
#[derive(Clone, Debug, PartialEq)]
pub struct GameObject {
pub id: u16,
- pub pos: Vector,
- pub orientation: Vector,
- pub shape: Shape,
- pub shape_params: Vec,
- pub vel: Vector,
- pub is_static: bool,
+ pub geom: Box,
+ pub physics: Box
}
impl GameObject {
-
pub fn update_pos(&mut self) {
- self.pos.add(&self.vel);
+ let center = self.geom.center_mut();
+ center.add(&self.vel);
// Keep last orientation if vel is now zero.
- if self.vel == Vector::zero() {
+ let vel = self.physics.vel();
+ if vel == Vector::zero() {
return;
}
- let mut orientation = self.vel.clone();
+ let mut orientation = vel.clone();
orientation.normalize();
self.orientation = orientation;
}
pub fn set_vel_x(&mut self, x: f64) {
- self.vel.x = x
+ let vel = self.physics.vel_mut();
+ vel.x = x;
}
pub fn set_vel_y(&mut self, y: f64) {
- self.vel.y = y
+ let vel = self.physics.vel_mut();
+ vel.y = y;
}
pub fn bounding_box(&self) -> BoundingBox {
- match self.shape {
- Shape::Rect => {
- BoundingBox::create(&self.pos, self.shape_params[0], self.shape_params[1])
- }
- Shape::Circle => {
- BoundingBox::create(&self.pos, self.shape_params[0] * 2, self.shape_params[0] * 2)
- }
- }
+ self.geom.shape().bounding_box()
+ }
+ }
+}
+
+pub mod components {
+ use crate::geom::geom::Vector;
+ use crate::geom::shape::Shape;
+
+ pub trait GeomComp {
+ fn orientation(&self) -> &Vector;
+ fn orientation_mut(&mut self) -> &mut Vector;
+ fn center(&self) -> &Vector;
+ fn center_mut(&mut self) -> &mut Vector;
+ }
+
+ pub struct DefaultGeomComp {
+ shape: Box
+ }
+ impl DefaultGeomComp {
+ pub fn new(shape: Box) -> DefaultGeomComp {
+ DefaultGeomComp {shape}
+ }
+ }
+ impl GeomComp for DefaultGeomComp {
+ fn orientation(&self) -> &Vector {
+ &self.shape.orientation()
+ }
+
+ fn orientation_mut(&mut self) -> &mut Vector {
+ &mut self.shape.orientation()
+ }
+
+ fn center(&self) -> &Vector {
+ &self.shape.center()
+ }
+
+ fn center_mut(&mut self) -> &mut Vector {
+ &mut self.shape.center()
+ }
+ }
+
+ pub trait PhysicsComp {
+ fn vel(&self) -> &Vector;
+ fn vel_mut(&mut self) -> &mut Vector;
+ fn is_static(&self) -> bool;
+ }
+
+ pub struct DefaultPhysicsComp {
+ vel: Vector,
+ is_static: bool
+ }
+ impl DefaultPhysicsComp {
+ pub fn new(vel: Vector, is_static: bool) -> DefaultPhysicsComp {
+ DefaultPhysicsComp {vel, is_static}
+ }
+ }
+ impl PhysicsComp for DefaultPhysicsComp {
+ fn vel(&self) -> &Vector {
+ &self.vel
+ }
+
+ fn vel_mut(&mut self) -> &mut Vector {
+ &mut self.vel
+ }
+
+ fn is_static(&self) -> bool {
+ self.is_static
}
}
}
diff --git a/pong/src/geom.rs b/pong/src/geom.rs
index 374f9c4..d78c212 100644
--- a/pong/src/geom.rs
+++ b/pong/src/geom.rs
@@ -143,29 +143,24 @@ pub mod geom {
}
impl BoundingBox {
- pub fn create_from_coords(x: f64, y: f64, width: u16, height: u16) -> BoundingBox {
- let center = Vector::new(x, y);
- return BoundingBox::create(¢er, width, height)
- }
-
- pub fn create(center: &Vector, width: u16, height: u16) -> BoundingBox {
+ pub fn create(center: &Vector, width: f64, height: f64) -> BoundingBox {
let center_x = center.x;
let center_y = center.y;
let top_left = Vector {
- x: center_x - (width as f64 / 2.),
- y: center_y + (height as f64 / 2.),
+ x: center_x - width / 2.,
+ y: center_y + height / 2.,
};
let top_right = Vector {
- x: center_x + (width as f64 / 2.),
- y: center_y + (height as f64 / 2.),
+ x: center_x + width / 2.,
+ y: center_y + height / 2.,
};
let bottom_left = Vector {
- x: center_x - (width as f64 / 2.),
- y: center_y - (height as f64 / 2.),
+ x: center_x - width / 2.,
+ y: center_y - height / 2.,
};
let bottom_right = Vector {
- x: center_x + (width as f64 / 2.),
- y: center_y - (height as f64 / 2.),
+ x: center_x + width / 2.,
+ y: center_y - height / 2.,
};
BoundingBox {
top_left,
@@ -242,3 +237,85 @@ pub mod geom {
}
}
}
+
+pub mod shape {
+ use crate::geom::geom::{BoundingBox, Vector};
+
+ #[derive(Clone, Debug, PartialEq)]
+ pub enum ShapeType {
+ Rect = 0,
+ Circle = 1,
+ }
+
+ pub trait Shape {
+ fn center(&self) -> &Vector;
+ fn orientation(&self) -> &Vector;
+ fn shape_type(&self) -> ShapeType;
+ fn bounding_box(&self) -> BoundingBox;
+ }
+
+ pub struct Rect {
+ pub width: f64,
+ pub height: f64,
+ center: Vector,
+ orientation: Vector
+ }
+
+ impl Rect {
+ pub fn new(center: Vector, orientation: Vector, width: f64, height: f64) -> Rect {
+ Rect {
+ center, orientation, width, height
+ }
+ }
+ }
+
+ impl Shape for Rect {
+ fn center(&self) -> &Vector {
+ &self.center
+ }
+
+ fn orientation(&self) -> &Vector {
+ &self.orientation
+ }
+
+ fn shape_type(&self) -> ShapeType {
+ ShapeType::Rect
+ }
+
+ fn bounding_box(&self) -> BoundingBox {
+ BoundingBox::create(self.center(), self.width, self.height)
+ }
+ }
+
+ pub struct Circle {
+ pub radius: f64,
+ center: Vector,
+ orientation: Vector,
+ }
+
+ impl Circle {
+ pub fn new(center: Vector, orientation: Vector, radius: f64) -> Circle {
+ Circle {
+ center, orientation, radius
+ }
+ }
+ }
+
+ impl Shape for Circle {
+ fn center(&self) -> &Vector {
+ &self.center
+ }
+
+ fn orientation(&self) -> &Vector {
+ &self.orientation
+ }
+
+ fn shape_type(&self) -> ShapeType {
+ ShapeType::Circle
+ }
+
+ fn bounding_box(&self) -> BoundingBox {
+ BoundingBox::create(&self.center(), self.radius * 2, self.radius * 2)
+ }
+ }
+}
diff --git a/pong/tests/collision_handler_test.rs b/pong/tests/collision_handler_test.rs
index cc60e74..04298d2 100644
--- a/pong/tests/collision_handler_test.rs
+++ b/pong/tests/collision_handler_test.rs
@@ -1,6 +1,6 @@
use rstest::rstest;
use pong::collision::collision::CollisionHandler;
-use pong::game_object::game_object::{GameObject, Shape};
+use pong::game_object::game_object::{GameObject, ShapeType};
use pong::geom::geom::Vector;
#[rstest]
diff --git a/pong/tests/collision_tests.rs b/pong/tests/collision_tests.rs
index 8cd9c3c..fbf9b99 100644
--- a/pong/tests/collision_tests.rs
+++ b/pong/tests/collision_tests.rs
@@ -1,6 +1,6 @@
use rstest::rstest;
use pong::collision::collision::{Collision, CollisionDetector};
-use pong::game_object::game_object::{GameObject, Shape};
+use pong::game_object::game_object::{GameObject, ShapeType};
use pong::geom::geom::{Vector};
#[rstest]
diff --git a/pong/tests/game_object_tests.rs b/pong/tests/game_object_tests.rs
index 077c4f3..0f35b70 100644
--- a/pong/tests/game_object_tests.rs
+++ b/pong/tests/game_object_tests.rs
@@ -1,5 +1,5 @@
use rstest::rstest;
-use pong::game_object::game_object::{GameObject, Shape};
+use pong::game_object::game_object::{GameObject, ShapeType};
use pong::geom::geom::{Vector};
#[rstest]
@@ -9,7 +9,7 @@ pub fn should_update_pos(#[case] start_pos: Vector, #[case] vel: Vector, #[case]
id: 1,
pos: Vector::new(start_pos.x as f64, start_pos.y as f64),
vel,
- shape: Shape::Rect,
+ shape: ShapeType::Rect,
shape_params: vec![],
is_static: false,
orientation: Vector::new(1., 0.)
diff --git a/src/lib.rs b/src/lib.rs
index 8aeddd8..57020ea 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -6,7 +6,7 @@ use std::cmp::{max, min};
use wasm_bindgen::prelude::*;
use pong::collision::collision::{Collision, CollisionDetector};
use pong::game_field::{Field, Input, InputType};
-use pong::game_object::game_object::{GameObject, Shape};
+use pong::game_object::game_object::{GameObject, ShapeType};
use pong::geom::geom::Vector;
use pong::utils::utils::Logger;