diff --git a/client/wasm/src/lib.rs b/client/wasm/src/lib.rs index 4cc6846..440ebb9 100644 --- a/client/wasm/src/lib.rs +++ b/client/wasm/src/lib.rs @@ -28,9 +28,9 @@ macro_rules! log { static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT; #[wasm_bindgen] -#[derive(Clone, Copy, Debug, PartialEq, Serialize)] +#[derive(Clone, Debug, PartialEq, Serialize)] pub struct GameObjectDTO { - pub id: u16, + id: String, pub x: f64, pub y: f64, pub orientation_x: f64, @@ -50,7 +50,7 @@ impl GameObjectDTO { let vel = obj.vel(); let shape = obj.shape(); return GameObjectDTO { - id: obj.id(), + id: obj.id().to_owned(), x: pos.x, y: pos.y, orientation_x: orientation.x, @@ -69,6 +69,14 @@ impl GameObjectDTO { } } +#[wasm_bindgen] +impl GameObjectDTO { + #[wasm_bindgen(getter)] + pub fn id(&self) -> String { + self.id.clone() + } +} + #[wasm_bindgen] #[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)] pub enum InputTypeDTO { @@ -86,23 +94,32 @@ impl InputTypeDTO { } #[wasm_bindgen] -#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] pub struct InputDTO { + obj_id: String, pub input: InputTypeDTO, - pub obj_id: u16, pub player: u16, } impl InputDTO { pub fn to_input(&self) -> Input { return Input { + obj_id: self.obj_id.clone(), input: self.input.to_input_type(), - obj_id: self.obj_id, player: self.player, }; } } +#[wasm_bindgen] +impl InputDTO { + #[wasm_bindgen(getter)] + pub fn obj_id(&self) -> String { + self.obj_id.clone() + } + +} + #[wasm_bindgen] pub struct FieldWrapper { field: Field, diff --git a/pong/src/collision.rs b/pong/src/collision.rs index 85ee112..489c923 100644 --- a/pong/src/collision.rs +++ b/pong/src/collision.rs @@ -74,7 +74,7 @@ pub mod detection { if !has_collision { continue; } - collisions.push(Collision(obj.id(), other.id())) + collisions.push(Collision(obj.id().to_owned(), other.id().to_owned())) } if i >= objs.len() { break; @@ -102,36 +102,36 @@ pub mod detection { #[case(vec![], vec![])] #[case( vec![ - MockGameObject::new(1, "a", BoundingBox::create(&Vector{x: 50., y: 50.}, 20., 20.)), - MockGameObject::new(2, "b", BoundingBox::create(&Vector{x: 50., y: 50.}, 20., 20.)) + MockGameObject::new("1", "a", BoundingBox::create(&Vector{x: 50., y: 50.}, 20., 20.)), + MockGameObject::new("2", "b", BoundingBox::create(&Vector{x: 50., y: 50.}, 20., 20.)) ], - vec![Collision(1, 2)] + vec![Collision::new("1", "2")] )] #[case( vec![ - MockGameObject::new(1, "a", BoundingBox::create(&Vector{x: 60., y: 65.}, 20., 20.)), - MockGameObject::new(2, "b", BoundingBox::create(&Vector{x: 50., y: 50.}, 20., 20.)), + MockGameObject::new("1", "a", BoundingBox::create(&Vector{x: 60., y: 65.}, 20., 20.)), + MockGameObject::new("2", "b", BoundingBox::create(&Vector{x: 50., y: 50.}, 20., 20.)), ], - vec![Collision(1, 2)] + vec![Collision::new("1", "2")] )] #[case( vec![ - MockGameObject::new(1, "a", BoundingBox::create(&Vector{x: 50., y: 50.}, 20., 20.)), - MockGameObject::new(2, "b", BoundingBox::create(&Vector{x: 80., y: 80.}, 20., 20.)), + MockGameObject::new("1", "a", BoundingBox::create(&Vector{x: 50., y: 50.}, 20., 20.)), + MockGameObject::new("2", "b", BoundingBox::create(&Vector{x: 80., y: 80.}, 20., 20.)), ], vec![] )] #[case( vec![ - MockGameObject::new(1, "a", BoundingBox::create(&Vector{x: 50., y: 50.}, 50., 50.)), - MockGameObject::new(2, "b", BoundingBox::create(&Vector{x: 500., y: 50.}, 50., 50.)), + MockGameObject::new("1", "a", BoundingBox::create(&Vector{x: 50., y: 50.}, 50., 50.)), + MockGameObject::new("2", "b", BoundingBox::create(&Vector{x: 500., y: 50.}, 50., 50.)), ], vec![] )] #[case( vec![ - MockGameObject::new(1, "a", BoundingBox::create(&Vector{x: 60., y: 65.}, 20., 20.)), - MockGameObject::new(2, "c", BoundingBox::create(&Vector{x: 50., y: 50.}, 20., 20.)), + MockGameObject::new("1", "a", BoundingBox::create(&Vector{x: 60., y: 65.}, 20., 20.)), + MockGameObject::new("2", "c", BoundingBox::create(&Vector{x: 50., y: 50.}, 20., 20.)), ], vec![] )] @@ -151,19 +151,19 @@ pub mod detection { #[derive(Debug)] pub struct MockGameObject { - id: u16, + id: String, obj_type: String, bounding_box: BoundingBox, } impl MockGameObject { pub fn new( - id: u16, + id: &str, obj_type: &str, bounding_box: BoundingBox, ) -> Rc>> { Rc::new(RefCell::new(Box::new(MockGameObject { - id, + id: id.to_owned(), obj_type: String::from(obj_type), bounding_box, }))) @@ -171,8 +171,8 @@ pub mod detection { } impl GameObject for MockGameObject { - fn id(&self) -> u16 { - self.id + fn id(&self) -> &str { + &self.id } fn obj_type(&self) -> &str { @@ -365,32 +365,32 @@ pub mod handler { #[rstest] #[case( - create_game_obj(1, Vector::new(1., 0.), Vector::new(1., 0.), true), - create_game_obj(2, Vector::new(0., 0.), Vector::new(0., 1.), true) + create_game_obj("1", Vector::new(1., 0.), Vector::new(1., 0.), true), + create_game_obj("2", Vector::new(0., 0.), Vector::new(0., 1.), true) )] #[case( - create_game_obj(1, Vector::new(1., 0.), Vector::new(1., 0.), false), - create_game_obj(2, Vector::new(0., 0.), Vector::new(0., 1.), true) + create_game_obj("1", Vector::new(1., 0.), Vector::new(1., 0.), false), + create_game_obj("2", Vector::new(0., 0.), Vector::new(0., 1.), true) )] #[case( - create_game_obj(1, Vector::new(-1., 0.), Vector::new(-1., 0.), false), - create_game_obj(2, Vector::new(0., 0.), Vector::new(0., 1.), true), + create_game_obj("1", Vector::new(-1., 0.), Vector::new(-1., 0.), false), + create_game_obj("2", Vector::new(0., 0.), Vector::new(0., 1.), true), )] #[case( - create_game_obj(1, Vector::new(1., 1.), Vector::new(1., 1.), false), - create_game_obj(2, Vector::new(0., 0.), Vector::new(0., 1.), true) + create_game_obj("1", Vector::new(1., 1.), Vector::new(1., 1.), false), + create_game_obj("2", Vector::new(0., 0.), Vector::new(0., 1.), true) )] #[case( - create_game_obj(1, Vector::new(-2., 1.), Vector::new(-1., 0.), false), - create_game_obj(2, Vector::new(0., 0.), Vector::new(0., 1.), true), + create_game_obj("1", Vector::new(-2., 1.), Vector::new(-1., 0.), false), + create_game_obj("2", Vector::new(0., 0.), Vector::new(0., 1.), true), )] #[case( - create_game_obj(1, Vector::new(1., 0.), Vector::new(1., 0.), false), - create_game_obj(2, Vector::new(0., 1.), Vector::new(0., 1.), true) + create_game_obj("1", Vector::new(1., 0.), Vector::new(1., 0.), false), + create_game_obj("2", Vector::new(0., 1.), Vector::new(0., 1.), true) )] #[case( - create_game_obj(1, Vector::new(-2., 1.), Vector::new(-1., 0.), false), - create_game_obj(2, Vector::new(0., 0.), Vector::new(0., 1.), true), + create_game_obj("1", Vector::new(-2., 1.), Vector::new(-1., 0.), false), + create_game_obj("2", Vector::new(0., 0.), Vector::new(0., 1.), true), )] pub fn should_handle_collision( #[case] obj_a: Rc>>, @@ -417,7 +417,7 @@ pub mod handler { } fn create_game_obj( - id: u16, + id: &str, vel: Vector, orientation: Vector, is_static: bool, @@ -442,7 +442,7 @@ pub mod collision { pub trait CollisionRegistry: Debug { fn get_collisions(&self) -> Vec<&Collision>; - fn get_collisions_by_id(&self, id: u16) -> Vec<&Collision>; + fn get_collisions_by_id(&self, id: &str) -> Vec<&Collision>; } #[derive(Debug)] @@ -460,7 +460,7 @@ pub mod collision { fn get_collisions(&self) -> Vec<&Collision> { self.state.iter().collect() } - fn get_collisions_by_id(&self, id: u16) -> Vec<&Collision> { + fn get_collisions_by_id(&self, id: &str) -> Vec<&Collision> { self.state .iter() .filter(|c| c.0 == id || c.1 == id) @@ -469,6 +469,12 @@ pub mod collision { } #[derive(Debug, Eq, PartialEq)] - pub struct Collision(pub u16, pub u16); + pub struct Collision(pub String, pub String); + + impl Collision { + pub fn new(obj_a: &str, obj_b: &str) -> Collision { + Collision(obj_a.to_owned(), obj_b.to_owned()) + } + } } diff --git a/pong/src/game_field.rs b/pong/src/game_field.rs index 824c459..57bcab7 100644 --- a/pong/src/game_field.rs +++ b/pong/src/game_field.rs @@ -2,7 +2,7 @@ use std::cell::RefCell; use std::rc::Rc; use serde::{Deserialize, Serialize}; -use crate::collision::collision::{Collision, CollisionRegistry, Collisions}; +use crate::collision::collision::{CollisionRegistry, Collisions}; use crate::collision::detection::{CollisionDetector, CollisionGroup}; use crate::collision::handler::{CollisionHandler, FieldStats}; use crate::game_object::components::{DefaultGeomComp, DefaultPhysicsComp}; @@ -26,7 +26,7 @@ pub enum InputType { #[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)] pub struct Input { pub input: InputType, - pub obj_id: u16, + pub obj_id: String, pub player: u16, } @@ -66,9 +66,9 @@ impl Field { logger_factory, }; - field.add_player(0, 0 + width / 15, height / 2); - field.add_player(1, width - width / 15, height / 2); - field.add_ball(2, width / 2, height / 2); + field.add_player("player_1", 0 + width / 15, height / 2); + field.add_player("player_2", width - width / 15, height / 2); + field.add_ball("ball_1", width / 2, height / 2); field.collision_handler.register( (String::from("ball"), String::from("player")), @@ -113,12 +113,12 @@ impl Field { } } - pub fn add_player(&mut self, id: u16, x: u16, y: u16) { - let player = DefaultGameObject::player(id, x, y, &self); + pub fn add_player(&mut self, id: &str, x: u16, y: u16) { + let player = DefaultGameObject::player(&id, x, y, &self); self.objs.push(Rc::new(RefCell::new(player))); } - pub fn add_ball(&mut self, id: u16, x: u16, y: u16) { + pub fn add_ball(&mut self, id: &str, x: u16, y: u16) { let ball = DefaultGameObject::ball(id, x, y, &self); self.objs.push(Rc::new(RefCell::new(ball))); } @@ -197,23 +197,23 @@ impl Field { } // TODO: Use slices. - let left_bound = self.objs.iter().filter(|o| o.borrow().obj_type() == "bound").collect::>>>>(); - let balls = self.objs.iter().filter(|o| o.borrow().obj_type() == "ball").collect::>>>>(); - let ball_ids = balls.iter().map(|b| b.borrow().id().clone()).collect::>(); - let ball_collisions = registered_collisions - .iter() - .map(|c| { - if ball_ids.contains(&c.0) { - return Some(c.1) - } - if ball_ids.contains(&c.1) { - return Some(c.0) - } - return None - }) - .filter(|v| v.is_some()) - .map(|c| self.objs.iter().find(|o| o.borrow().id() == c.unwrap()).unwrap()) - .collect::>>>>(); + // let left_bound = self.objs.iter().filter(|o| o.borrow().obj_type() == "bound").collect::>>>>(); + // let balls = self.objs.iter().filter(|o| o.borrow().obj_type() == "ball").collect::>>>>(); + // let ball_ids = balls.iter().map(|b| b.borrow().id().to_owned()).collect::>(); + // let ball_collisions = registered_collisions + // .iter() + // .map(|c| { + // if ball_ids.contains(&c.0) { + // return Some(c.1.clone()) + // } + // if ball_ids.contains(&c.1) { + // return Some(c.0.clone()) + // } + // return None + // }) + // .filter(|v| v.is_some()) + // .map(|c| self.objs.iter().find(|o| o.borrow().id() == c.unwrap()).unwrap()) + // .collect::>>>>(); { for obj in self.objs.iter().filter(|o| RefCell::borrow(o).is_dirty()) { @@ -251,7 +251,7 @@ impl Field { } impl DefaultGameObject { - pub fn player(id: u16, x: u16, y: u16, field: &Field) -> Box { + pub fn player(id: &str, x: u16, y: u16, field: &Field) -> Box { Box::new(DefaultGameObject::new( id, "player".to_string(), @@ -270,7 +270,7 @@ impl DefaultGameObject { } impl DefaultGameObject { - pub fn ball(id: u16, x: u16, y: u16, field: &Field) -> Box { + pub fn ball(id: &str, x: u16, y: u16, field: &Field) -> Box { Box::new(DefaultGameObject::new( id, "ball".to_string(), @@ -293,7 +293,7 @@ impl DefaultGameObject { Bounds( Bound::BOTTOM, Box::new(DefaultGameObject::new( - 90, + "bound_bottom", "bound".to_string(), Box::new(DefaultGeomComp::new(Shape::rect( Vector { @@ -310,7 +310,7 @@ impl DefaultGameObject { Bounds( Bound::TOP, Box::new(DefaultGameObject::new( - 91, + "bound_top", "bound".to_string(), Box::new(DefaultGeomComp::new(Shape::rect( Vector { @@ -327,7 +327,7 @@ impl DefaultGameObject { Bounds( Bound::LEFT, Box::new(DefaultGameObject::new( - 92, + "bound_left", "bound".to_string(), Box::new(DefaultGeomComp::new(Shape::rect( Vector { @@ -344,7 +344,7 @@ impl DefaultGameObject { Bounds( Bound::RIGHT, Box::new(DefaultGameObject::new( - 93, + "bound_right", "bound".to_string(), Box::new(DefaultGeomComp::new(Shape::rect( Vector { @@ -389,10 +389,10 @@ mod tests { let width = 1000; let height = 1000; let mut field = Field::mock(width, height); - field.add_player(1, 50, height / 2); + field.add_player("player_1", 50, height / 2); let inputs = vec![Input { input: InputType::UP, - obj_id: 1, + obj_id: "player_1".to_owned(), player: 1, }]; field.tick(inputs, 1.); @@ -410,10 +410,10 @@ mod tests { fn player_input_update_pos_down() { let height = 1000; let mut field = Field::mock(1000, height); - field.add_player(1, 50, height / 2); + field.add_player("player_1", 50, height / 2); let inputs = vec![Input { input: InputType::DOWN, - obj_id: 1, + obj_id: "player_1".to_owned(), player: 1, }]; field.tick(inputs, 1.); diff --git a/pong/src/game_object.rs b/pong/src/game_object.rs index 6538d0c..d1964b2 100644 --- a/pong/src/game_object.rs +++ b/pong/src/game_object.rs @@ -6,7 +6,7 @@ pub mod game_object { use std::fmt::Debug; pub trait GameObject: Debug { - fn id(&self) -> u16; + fn id(&self) -> &str; fn obj_type(&self) -> &str; fn shape(&self) -> &ShapeType; fn pos(&self) -> &Vector; @@ -24,7 +24,7 @@ pub mod game_object { #[derive(Debug)] pub struct DefaultGameObject { - pub id: u16, + pub id: String, pub obj_type: String, geom: Box, physics: Box, @@ -33,13 +33,13 @@ pub mod game_object { impl DefaultGameObject { pub fn new( - id: u16, + id: &str, obj_type: String, geom: Box, physics: Box, ) -> DefaultGameObject { DefaultGameObject { - id, + id: id.to_owned(), obj_type, geom, physics, @@ -49,8 +49,8 @@ pub mod game_object { } impl GameObject for DefaultGameObject { - fn id(&self) -> u16 { - self.id + fn id(&self) -> &str { + &self.id } fn obj_type(&self) -> &str { @@ -139,7 +139,7 @@ pub mod game_object { #[case] ms_diff: f64, ) { let mut obj = DefaultGameObject::new( - 1, + "1", "obj".to_string(), Box::new(DefaultGeomComp::new(Shape::rect( Vector::new(start_pos.x as f64, start_pos.y as f64), diff --git a/pong/src/pong.rs b/pong/src/pong.rs index b0827db..34b553a 100644 --- a/pong/src/pong.rs +++ b/pong/src/pong.rs @@ -128,34 +128,34 @@ pub mod pong_collisions { #[rstest] #[case( // given - create_player(1, 10, 0, Vector::new(0., -1.)), + create_player("1", 10, 0, Vector::new(0., -1.)), get_bound(Bound::BOTTOM), // expected - create_player(1, 10, 31, Vector::new(0., -1.)), + create_player("2", 10, 31, Vector::new(0., -1.)), get_bound(Bound::BOTTOM) )] #[case( // given - create_player(1, 10, 1, Vector::new(0., -1.)), + create_player("1", 10, 1, Vector::new(0., -1.)), get_bound(Bound::BOTTOM), // expected - create_player(1, 10, 31, Vector::new(0., -1.)), + create_player("2", 10, 31, Vector::new(0., -1.)), get_bound(Bound::BOTTOM) )] #[case( // given - create_player(1, 10, 601, Vector::new(0., 1.)), + create_player("1", 10, 601, Vector::new(0., 1.)), get_bound(Bound::TOP), // expected - create_player(1, 10, 569, Vector::new(0., 1.)), + create_player("2", 10, 569, Vector::new(0., 1.)), get_bound(Bound::TOP) )] #[case( // given - create_player(1, 10, 599, Vector::new(0., 1.)), + create_player("1", 10, 599, Vector::new(0., 1.)), get_bound(Bound::TOP), // expected - create_player(1, 10, 569, Vector::new(0., 1.)), + create_player("2", 10, 569, Vector::new(0., 1.)), get_bound(Bound::TOP) )] pub fn should_correctly_handle_player_bounds_collision( @@ -170,7 +170,7 @@ pub mod pong_collisions { assert_eq!(bounds_expected.borrow().pos(), bounds.borrow().pos()); } - fn create_player(id: u16, x: u16, y: u16, orientation: Vector) -> Rc>> { + fn create_player(id: &str, x: u16, y: u16, orientation: Vector) -> Rc>> { let logger = DefaultLoggerFactory::noop(); let event_writer = NoopPongEventWriter::new(); let field = Field::new(logger, event_writer);