mirror of
https://github.com/thilo-behnke/wasm-pong.git
synced 2026-08-18 04:36:14 +00:00
migrate game obj pos to float
This commit is contained in:
+8
-14
@@ -90,10 +90,10 @@ impl Field {
|
||||
}
|
||||
|
||||
for player in self.players.iter_mut() {
|
||||
player.obj.update_pos(self.width, self.height)
|
||||
player.obj.update_pos()
|
||||
}
|
||||
for ball in self.balls.iter_mut() {
|
||||
ball.obj.update_pos(self.width, self.height)
|
||||
ball.obj.update_pos()
|
||||
}
|
||||
|
||||
let mut objs: Vec<GameObject> = vec![];
|
||||
@@ -155,8 +155,7 @@ impl Player {
|
||||
Player {
|
||||
obj: GameObject {
|
||||
id,
|
||||
x,
|
||||
y,
|
||||
pos: Vector {x: x as f64, y: y as f64},
|
||||
shape: Shape::Rect,
|
||||
shape_params: vec![field.width / 25, field.height / 5],
|
||||
vel: Vector::zero(),
|
||||
@@ -176,8 +175,7 @@ impl Ball {
|
||||
Ball {
|
||||
obj: GameObject {
|
||||
id,
|
||||
x,
|
||||
y,
|
||||
pos: Vector {x: x as f64, y: y as f64},
|
||||
shape: Shape::Circle,
|
||||
shape_params: vec![field.width / 80],
|
||||
vel: Vector::zero(),
|
||||
@@ -198,8 +196,7 @@ impl Bounds {
|
||||
objs: vec![
|
||||
GameObject {
|
||||
id: 90,
|
||||
x: width / 2,
|
||||
y: 0,
|
||||
pos: Vector {x: (width / 2) as f64, y: 0 as f64},
|
||||
shape: Shape::Rect,
|
||||
shape_params: vec![width, 2],
|
||||
is_static: true,
|
||||
@@ -208,8 +205,7 @@ impl Bounds {
|
||||
// bottom
|
||||
GameObject {
|
||||
id: 91,
|
||||
x: width / 2,
|
||||
y: height,
|
||||
pos: Vector {x: (width / 2) as f64, y: height as f64},
|
||||
shape: Shape::Rect,
|
||||
shape_params: vec![width, 2],
|
||||
is_static: true,
|
||||
@@ -218,8 +214,7 @@ impl Bounds {
|
||||
// left
|
||||
GameObject {
|
||||
id: 92,
|
||||
x: 0,
|
||||
y: height / 2,
|
||||
pos: Vector {x: 0 as f64, y: (height / 2) as f64},
|
||||
shape: Shape::Rect,
|
||||
shape_params: vec![2, height],
|
||||
is_static: true,
|
||||
@@ -228,8 +223,7 @@ impl Bounds {
|
||||
// right
|
||||
GameObject {
|
||||
id: 93,
|
||||
x: width,
|
||||
y: height / 2,
|
||||
pos: Vector {x: width as f64, y: (height / 2) as f64},
|
||||
shape: Shape::Rect,
|
||||
shape_params: vec![2, height],
|
||||
is_static: true,
|
||||
|
||||
+6
-22
@@ -10,8 +10,7 @@ pub mod game_object {
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub struct GameObject {
|
||||
pub id: u16,
|
||||
pub x: u16,
|
||||
pub y: u16,
|
||||
pub pos: Vector,
|
||||
pub shape: Shape,
|
||||
pub shape_params: Vec<u16>,
|
||||
pub vel: Vector,
|
||||
@@ -19,20 +18,9 @@ pub mod game_object {
|
||||
}
|
||||
|
||||
impl GameObject {
|
||||
// TODO: Migrate pos to f64
|
||||
pub fn update_pos(&mut self, field_width: u16, field_height: u16) {
|
||||
let abs_x = self.vel.x.abs() as u16;
|
||||
let updated_x = match self.vel.x {
|
||||
n if n >= 0. => self.x.wrapping_add(abs_x),
|
||||
_ => self.x.wrapping_sub(abs_x)
|
||||
};
|
||||
let abs_y = self.vel.y.abs() as u16;
|
||||
let updated_y = match self.vel.y {
|
||||
n if n >= 0. => self.y.wrapping_add(abs_y),
|
||||
_ => self.y.wrapping_sub(abs_y)
|
||||
};
|
||||
self.x = updated_x;
|
||||
self.y = updated_y;
|
||||
|
||||
pub fn update_pos(&mut self) {
|
||||
self.pos.add(&self.vel);
|
||||
}
|
||||
|
||||
pub fn set_vel_x(&mut self, x: f64) {
|
||||
@@ -44,16 +32,12 @@ pub mod game_object {
|
||||
}
|
||||
|
||||
pub fn bounding_box(&self) -> BoundingBox {
|
||||
self.bounding_box_from(self.x, self.y)
|
||||
}
|
||||
|
||||
fn bounding_box_from(&self, x: u16, y: u16) -> BoundingBox {
|
||||
match self.shape {
|
||||
Shape::Rect => {
|
||||
BoundingBox::create(x, y, self.shape_params[0], self.shape_params[1])
|
||||
BoundingBox::create(&self.pos, self.shape_params[0], self.shape_params[1])
|
||||
}
|
||||
Shape::Circle => {
|
||||
BoundingBox::create(x, y, self.shape_params[0] * 2, self.shape_params[0] * 2)
|
||||
BoundingBox::create(&self.pos, self.shape_params[0] * 2, self.shape_params[0] * 2)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+39
-31
@@ -1,5 +1,5 @@
|
||||
pub mod geom {
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Vector {
|
||||
pub x: f64,
|
||||
pub y: f64,
|
||||
@@ -54,6 +54,11 @@ pub mod geom {
|
||||
self.y += other.y;
|
||||
}
|
||||
|
||||
pub fn sub(&mut self, other: &Vector) {
|
||||
self.x -= other.x;
|
||||
self.y -= other.y;
|
||||
}
|
||||
|
||||
pub fn invert(&mut self) {
|
||||
self.x = self.x * -1.;
|
||||
self.y = self.y * -1.;
|
||||
@@ -81,30 +86,44 @@ pub mod geom {
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for Vector {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
(self.x * 1000.).round() == (other.x * 1000.).round() &&
|
||||
(self.y * 1000.).round() == (other.y * 1000.).round()
|
||||
}
|
||||
}
|
||||
|
||||
pub struct BoundingBox {
|
||||
top_left: Point,
|
||||
top_right: Point,
|
||||
bottom_left: Point,
|
||||
bottom_right: Point,
|
||||
top_left: Vector,
|
||||
top_right: Vector,
|
||||
bottom_left: Vector,
|
||||
bottom_right: Vector,
|
||||
}
|
||||
|
||||
impl BoundingBox {
|
||||
pub fn create(center_x: u16, center_y: u16, width: u16, height: u16) -> BoundingBox {
|
||||
let top_left = Point {
|
||||
x: center_x as i32 - (width / 2) as i32,
|
||||
y: center_y as i32 + (height / 2) as i32,
|
||||
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 {
|
||||
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.),
|
||||
};
|
||||
let top_right = Point {
|
||||
x: center_x as i32 + (width / 2) as i32,
|
||||
y: center_y as i32 + (height / 2) as i32,
|
||||
let top_right = Vector {
|
||||
x: center_x + (width as f64 / 2.),
|
||||
y: center_y + (height as f64 / 2.),
|
||||
};
|
||||
let bottom_left = Point {
|
||||
x: center_x as i32 - (width / 2) as i32,
|
||||
y: center_y as i32 - (height / 2) as i32,
|
||||
let bottom_left = Vector {
|
||||
x: center_x - (width as f64 / 2.),
|
||||
y: center_y - (height as f64 / 2.),
|
||||
};
|
||||
let bottom_right = Point {
|
||||
x: center_x as i32 + (width / 2) as i32,
|
||||
y: center_y as i32 - (height / 2) as i32,
|
||||
let bottom_right = Vector {
|
||||
x: center_x + (width as f64 / 2.),
|
||||
y: center_y - (height as f64 / 2.),
|
||||
};
|
||||
BoundingBox {
|
||||
top_left,
|
||||
@@ -114,7 +133,7 @@ pub mod geom {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn points(&self) -> Vec<&Point> {
|
||||
pub fn points(&self) -> Vec<&Vector> {
|
||||
return vec![
|
||||
&self.top_left,
|
||||
&self.top_right,
|
||||
@@ -127,22 +146,11 @@ pub mod geom {
|
||||
return self.points().iter().any(|p| other.is_point_within(p)) || other.points().iter().any(|p| self.is_point_within(p));
|
||||
}
|
||||
|
||||
pub fn is_point_within(&self, point: &Point) -> bool {
|
||||
pub fn is_point_within(&self, point: &Vector) -> bool {
|
||||
return point.x >= self.top_left.x
|
||||
&& point.x <= self.top_right.x
|
||||
&& point.y <= self.top_left.y
|
||||
&& point.y >= self.bottom_left.y;
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Point {
|
||||
pub x: i32,
|
||||
pub y: i32,
|
||||
}
|
||||
|
||||
impl Point {
|
||||
pub fn create(x: i32, y: i32) -> Point {
|
||||
Point { x, y }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
use rstest::rstest;
|
||||
use pong::geom::geom::{BoundingBox, Point};
|
||||
use pong::geom::geom::{BoundingBox, Vector};
|
||||
|
||||
#[rstest]
|
||||
#[case(BoundingBox::create(10, 10, 5, 5), Point::create(10, 10), true)]
|
||||
#[case(BoundingBox::create(10, 10, 5, 5), Point::create(8, 8), true)]
|
||||
#[case(BoundingBox::create(10, 10, 5, 5), Point::create(20, 20), false)]
|
||||
#[case(BoundingBox::create_from_coords(10., 10., 5, 5), Vector::new(10., 10.), true)]
|
||||
#[case(BoundingBox::create_from_coords(10., 10., 5, 5), Vector::new(8., 8.), true)]
|
||||
#[case(BoundingBox::create_from_coords(10., 10., 5, 5), Vector::new(20., 20.), false)]
|
||||
pub fn should_correctly_determine_if_point_is_within_box(
|
||||
#[case] bounding_box: BoundingBox,
|
||||
#[case] point: Point,
|
||||
#[case] point: Vector,
|
||||
#[case] expected: bool,
|
||||
) {
|
||||
let res = bounding_box.is_point_within(&point);
|
||||
@@ -16,20 +16,25 @@ pub fn should_correctly_determine_if_point_is_within_box(
|
||||
|
||||
#[rstest]
|
||||
#[case(
|
||||
BoundingBox::create(10, 10, 5, 5),
|
||||
BoundingBox::create(10, 10, 5, 5),
|
||||
BoundingBox::create_from_coords(10., 10., 5, 5),
|
||||
BoundingBox::create_from_coords(10., 10., 5, 5),
|
||||
true
|
||||
)]
|
||||
#[case(
|
||||
BoundingBox::create(10, 10, 5, 5),
|
||||
BoundingBox::create(8, 8, 5, 5),
|
||||
BoundingBox::create_from_coords(10., 10., 5, 5),
|
||||
BoundingBox::create_from_coords(8., 8., 5, 5),
|
||||
true
|
||||
)]
|
||||
#[case(
|
||||
BoundingBox::create(10, 10, 5, 5),
|
||||
BoundingBox::create(5, 5, 5, 5),
|
||||
BoundingBox::create_from_coords(10., 10., 5, 5),
|
||||
BoundingBox::create_from_coords(4.9, 4.9, 5, 5),
|
||||
false
|
||||
)]
|
||||
#[case(
|
||||
BoundingBox::create_from_coords(10., 10., 5, 5),
|
||||
BoundingBox::create_from_coords(5., 5., 5, 5),
|
||||
true
|
||||
)]
|
||||
pub fn should_correctly_determine_if_overlap(
|
||||
#[case] bounding_box_a: BoundingBox,
|
||||
#[case] bounding_box_b: BoundingBox,
|
||||
|
||||
@@ -7,29 +7,29 @@ use pong::geom::geom::{Vector};
|
||||
#[case(vec![], vec![])]
|
||||
#[case(
|
||||
vec![
|
||||
GameObject{id: 1, x: 50, y: 50, shape: Shape::Rect, shape_params: vec![20, 20], vel: Vector::zero(), is_static: false},
|
||||
GameObject{id: 2, 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},
|
||||
GameObject{id: 2, pos: Vector{x: 50., y: 50.}, shape: Shape::Rect, shape_params: vec![20, 20], vel: Vector::zero(), is_static: false}
|
||||
],
|
||||
vec![Collision(1, 2)]
|
||||
)]
|
||||
#[case(
|
||||
vec![
|
||||
GameObject{id: 1, x: 60, y: 65, shape: Shape::Rect, shape_params: vec![20, 20], vel: Vector::zero(), is_static: false},
|
||||
GameObject{id: 2, 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},
|
||||
GameObject{id: 2, pos: Vector{x: 50., y: 50.}, shape: Shape::Rect, shape_params: vec![20, 20], vel: Vector::zero(), is_static: false}
|
||||
],
|
||||
vec![Collision(1, 2)]
|
||||
)]
|
||||
#[case(
|
||||
vec![
|
||||
GameObject{id: 1, x: 50, y: 50, shape: Shape::Rect, shape_params: vec![20, 20], vel: Vector::zero(), is_static: false},
|
||||
GameObject{id: 2, 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},
|
||||
GameObject{id: 2, pos: Vector{x: 80., y: 80.}, shape: Shape::Rect, shape_params: vec![20, 20], vel: Vector::zero(), is_static: false}
|
||||
],
|
||||
vec![]
|
||||
)]
|
||||
#[case(
|
||||
vec![
|
||||
GameObject{id: 1, x: 50, y: 50, shape: Shape::Rect, shape_params: vec![50, 50], vel: Vector::zero(), is_static: false},
|
||||
GameObject{id: 2, 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},
|
||||
GameObject{id: 2, pos: Vector{x: 500., y: 50.}, shape: Shape::Rect, shape_params: vec![50, 50], vel: Vector::zero(), is_static: false}
|
||||
],
|
||||
vec![]
|
||||
)]
|
||||
|
||||
@@ -14,7 +14,7 @@ mod game_field_tests {
|
||||
field.tick(inputs);
|
||||
let players = field.players();
|
||||
let player = players.first().unwrap();
|
||||
assert_eq!(player.obj.y, height / 2 + 1);
|
||||
assert_eq!(player.obj.pos.y, height as f64 / 2. + 1.);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -29,7 +29,7 @@ mod game_field_tests {
|
||||
field.tick(inputs);
|
||||
let players = field.players();
|
||||
let player = players.first().unwrap();
|
||||
assert_eq!(player.obj.y, height / 2 - 1);
|
||||
assert_eq!(player.obj.pos.y, height as f64 / 2. - 1.);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -44,7 +44,7 @@ mod game_field_tests {
|
||||
field.tick(inputs);
|
||||
let players = field.players();
|
||||
let player = players.first().unwrap();
|
||||
assert_eq!(player.obj.y, height - height / 5 / 2);
|
||||
assert_eq!(player.obj.pos.y, height as f64 - height as f64 / 5. / 2.);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -59,6 +59,6 @@ mod game_field_tests {
|
||||
field.tick(inputs);
|
||||
let players = field.players();
|
||||
let player = players.first().unwrap();
|
||||
assert_eq!(player.obj.y, height / 5 / 2);
|
||||
assert_eq!(player.obj.pos.y, height as f64 / 5. / 2.);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,20 +1,18 @@
|
||||
use rstest::rstest;
|
||||
use pong::game_object::game_object::{GameObject, Shape};
|
||||
use pong::geom::geom::{Point, Vector};
|
||||
use pong::geom::geom::{Vector};
|
||||
|
||||
#[rstest]
|
||||
#[case(Point::create(100, 100), Vector::new(-1., 1.), Point::create(99, 101))]
|
||||
pub fn should_update_pos(#[case] start_pos: Point, #[case] vel: Vector, #[case] expected_pos: Point) {
|
||||
#[case(Vector::new(100., 100.), Vector::new(-1., 1.), Vector::new(99., 101.))]
|
||||
pub fn should_update_pos(#[case] start_pos: Vector, #[case] vel: Vector, #[case] expected_pos: Vector) {
|
||||
let mut obj = GameObject {
|
||||
id: 1,
|
||||
x: start_pos.x as u16,
|
||||
y: start_pos.y as u16,
|
||||
pos: Vector::new(start_pos.x as f64, start_pos.y as f64),
|
||||
vel,
|
||||
shape: Shape::Rect,
|
||||
shape_params: vec![],
|
||||
is_static: false,
|
||||
};
|
||||
obj.update_pos(1000, 1000);
|
||||
assert_eq!(obj.x, expected_pos.x as u16);
|
||||
assert_eq!(obj.y, expected_pos.y as u16);
|
||||
obj.update_pos();
|
||||
assert_eq!(obj.pos, expected_pos);
|
||||
}
|
||||
|
||||
+2
-2
@@ -40,8 +40,8 @@ impl GameObjectDTO {
|
||||
pub fn from(obj: &GameObject) -> GameObjectDTO {
|
||||
return GameObjectDTO {
|
||||
id: obj.id,
|
||||
x: obj.x,
|
||||
y: obj.y,
|
||||
x: obj.pos.x as u16,
|
||||
y: obj.pos.y as u16,
|
||||
shape_param_1: match obj.shape_params[..] {
|
||||
[p1, _] => p1,
|
||||
[p1] => p1,
|
||||
|
||||
Reference in New Issue
Block a user