diff --git a/pong/src/collision.rs b/pong/src/collision.rs index 2650470..d3381e4 100644 --- a/pong/src/collision.rs +++ b/pong/src/collision.rs @@ -2,7 +2,7 @@ pub mod collision { use crate::game_object::game_object::GameObject; use crate::geom::geom::Vector; use std::alloc::handle_alloc_error; - use std::cell::{Ref, RefCell}; + use std::cell::{Ref, RefCell, RefMut}; use std::collections::HashMap; use std::fmt::Debug; use std::rc::Rc; @@ -78,7 +78,7 @@ pub mod collision { #[derive(Clone)] pub struct CollisionHandler { - handlers: HashMap<(String, String), fn(&mut Box, &mut Box)>, + handlers: HashMap<(String, String), fn(Rc>>, Rc>>)> } impl CollisionHandler { @@ -91,7 +91,7 @@ pub mod collision { pub fn register( &mut self, mapping: (String, String), - callback: fn(&mut Box, &mut Box), + callback: fn(Rc>>, Rc>>), ) { if self.handlers.contains_key(&mapping) { panic!( @@ -104,10 +104,10 @@ pub mod collision { pub fn handle( &self, - obj_a: &mut Box, - obj_b: &mut Box, + obj_a: Rc>>, + obj_b: Rc>>, ) -> bool { - let key = (obj_a.obj_type().to_string(), obj_b.obj_type().to_string()); + let key = (RefCell::borrow(&obj_a).obj_type().to_string(), RefCell::borrow(&obj_b).obj_type().to_string()); if !self.handlers.contains_key(&key) { return false; } diff --git a/pong/src/game_field.rs b/pong/src/game_field.rs index c7dfdb3..4843d2d 100644 --- a/pong/src/game_field.rs +++ b/pong/src/game_field.rs @@ -136,6 +136,7 @@ impl Field { { for obj in self.objs.iter() { let mut obj_mut = RefCell::borrow_mut(obj); + self.logger.log("update player"); obj_mut.update_pos(); } } @@ -144,35 +145,12 @@ impl Field { let collision_handler = self.collision_handler.clone(); for collision in collisions.get_collisions().iter() { - // TODO: This is fine because an obj will not collide with itself - better abstraction? - // let idx - // let (obj_a, obj_b) = self.objs.split_at_mut(); - // let obj_a = self.get_obj(collision.0, self.objs.borrow_mut()); - // let obj_b = self.get_obj(collision.1, self.objs.borrow_mut()); - // collision_handler.handle(obj_a, obj_b) + let objs = &self.objs; + let obj_a = objs.iter().find(|o| RefCell::borrow(o).id() == collision.0).unwrap().clone(); + let obj_b = objs.iter().find(|o| RefCell::borrow(o).id() == collision.1).unwrap().clone(); + self.logger.log(&*format!("Handling collision between {:?} and {:?}", obj_a, obj_b)); + collision_handler.handle(obj_a, obj_b); } - // - // for ball in self.balls.iter_mut() { - // let collisions = self.collisions.get_collisions_by_id(ball.obj.id()); - // if collisions.is_empty() { - // continue; - // } - // let other = match collisions[0] { - // Collision(obj_a_id, obj_b_id) if *obj_a_id == ball.obj.id() => { - // objs.iter().find(|o| o.id() == *obj_b_id).unwrap() - // } - // collision => objs.iter().find(|o| o.id() == collision.0).unwrap(), - // }; - // - // self.logger.log("### BEFORE COLLISION ###"); - // self.logger.log(&*format!("{:?}", ball.obj)); - // self.logger.log(&*format!("{:?}", other)); - // collision_handler.handle(&mut ball.obj, other); - // self.logger.log("### AFTER COLLISION ###"); - // self.logger.log(&*format!("{:?}", ball.obj)); - // self.logger.log(&*format!("{:?}", other)); - // self.logger.log("### DONE ###"); - // } } fn get_collisions(&self) -> Box { diff --git a/pong/src/pong.rs b/pong/src/pong.rs index 9e291fa..25e2114 100644 --- a/pong/src/pong.rs +++ b/pong/src/pong.rs @@ -1,14 +1,18 @@ pub mod pong_collisions { + use std::cell::{RefCell, RefMut}; use std::ops::Add; + use std::rc::Rc; use crate::game_object::game_object::GameObject; use crate::geom::geom::Vector; use crate::geom::shape::ShapeType; pub fn handle_player_ball_collision( - ball: &mut Box, - player: &mut Box, + ball: Rc>>, + player: Rc>>, ) { // reflect + let mut ball = RefCell::borrow_mut(&ball); + let player = player.borrow(); ball.vel_mut().reflect(&player.orientation()); // use vel of player obj if *player.vel() != Vector::zero() { @@ -24,16 +28,20 @@ pub mod pong_collisions { } pub fn handle_ball_bounds_collision( - ball: &mut Box, - bound: &mut Box, + ball: Rc>>, + bound: Rc>>, ) { + let mut ball = RefCell::borrow_mut(&ball); + let bound = RefCell::borrow(&bound); ball.vel_mut().reflect(&bound.orientation()); } pub fn handle_player_bound_collision( - player: &mut Box, - bound: &mut Box, + player: Rc>>, + bound: Rc>>, ) { + let mut player = RefCell::borrow_mut(&player); + let bound = RefCell::borrow(&bound); let shape = player.shape().clone(); let player_orientation = player.orientation().clone(); let height = match shape { diff --git a/pong/tests/collision_tests.rs b/pong/tests/collision_tests.rs index 577533b..db08385 100644 --- a/pong/tests/collision_tests.rs +++ b/pong/tests/collision_tests.rs @@ -90,6 +90,10 @@ impl GameObject for MockGameObject { todo!() } + fn orientation_mut(&mut self) -> &mut Vector { + todo!() + } + fn update_pos(&mut self) { todo!() } diff --git a/pong/tests/pong_tests.rs b/pong/tests/pong_tests.rs index c65a59d..1af47d9 100644 --- a/pong/tests/pong_tests.rs +++ b/pong/tests/pong_tests.rs @@ -1,3 +1,5 @@ +use std::cell::RefCell; +use std::rc::Rc; use rstest::rstest; use pong::game_field::{Bound, Field}; use pong::game_object::game_object::{DefaultGameObject, GameObject}; @@ -47,29 +49,29 @@ use pong::utils::utils::NoopLogger; get_bound(Bound::TOP) )] pub fn should_correctly_handle_player_bounds_collision( - #[case] mut player: Box, - #[case] mut bounds: Box, - #[case] mut player_expected: Box, - #[case] mut bounds_expected: Box + #[case] mut player: Rc>>, + #[case] mut bounds: Rc>>, + #[case] mut player_expected: Rc>>, + #[case] mut bounds_expected: Rc>> ) { - handle_player_bound_collision(&mut player, &mut bounds); - assert_eq!(player_expected.pos(), player.pos()); - assert_eq!(bounds_expected.pos(), bounds.pos()); + handle_player_bound_collision(player.clone(), bounds.clone()); + assert_eq!(player_expected.borrow().pos(), player.borrow().pos()); + assert_eq!(bounds_expected.borrow().pos(), bounds.borrow().pos()); } -fn create_player(id: u16, x: u16, y: u16, orientation: Vector) -> Box { +fn create_player(id: u16, x: u16, y: u16, orientation: Vector) -> Rc>> { let field = Field::new(Box::new(NoopLogger{})); let mut player = DefaultGameObject::player(id, x, y, &field); let player_orientation = player.orientation_mut(); player_orientation.x = orientation.x; player_orientation.y = orientation.y; - player + Rc::new(RefCell::new(player)) } -fn get_bound(bound: Bound) -> Box { +fn get_bound(bound: Bound) -> Rc>> { let field = Field::new(Box::new(NoopLogger{})); let bounds = DefaultGameObject::bounds(field.width, field.height); - return bounds.into_iter().find(|b| { + return Rc::new(RefCell::new(bounds.into_iter().find(|b| { b.0 == bound - }).unwrap().inner(); + }).unwrap().inner())); } diff --git a/src/lib.rs b/src/lib.rs index 8d7f8ae..de1b15e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,5 +1,6 @@ mod utils; +use std::cell::RefCell; use pong::collision::collision::{Collision, CollisionDetector}; use pong::game_field::{Field, Input, InputType}; use pong::game_object::game_object::GameObject; @@ -9,6 +10,7 @@ use pong::utils::utils::Logger; use serde::{Deserialize, Serialize}; use serde_json::json; use std::cmp::{max, min}; +use std::rc::Rc; use wasm_bindgen::prelude::*; extern crate serde_json; @@ -39,7 +41,9 @@ pub struct GameObjectDTO { } impl GameObjectDTO { - pub fn from(obj: &Box) -> GameObjectDTO { + pub fn from(obj: &Rc>>) -> GameObjectDTO { + let obj = RefCell::borrow(obj); + let pos = obj.pos(); let shape = obj.shape(); return GameObjectDTO { @@ -123,9 +127,8 @@ impl FieldWrapper { pub fn objects(&self) -> *const GameObjectDTO { let mut objs = self .field - .objs - .borrow() - .iter() + .objs() + .into_iter() .map(|o| GameObjectDTO::from(o)) .collect::>(); objs.as_ptr()