use crate::event::EventStruct; pub struct Body { pub position: glam::Vec3,//I64 where 2^32 = 1 u pub velocity: glam::Vec3,//I64 where 2^32 = 1 u/s pub time: TIME,//nanoseconds x xxxxD! } pub struct PhysicsState { pub body: Body, pub contacts: Vec, pub time: TIME, pub strafe_tick_num: TIME, pub strafe_tick_den: TIME, pub tick: u32, pub mv: f32, pub walkspeed: f32, pub friction: f32, pub gravity: glam::Vec3, pub grounded: bool, pub jump_trying: bool, } pub struct RelativeCollision { face: Face,//just an id model: u32,//using id to avoid lifetimes } impl RelativeCollision { pub fn mesh(&self,models:&Vec) -> TreyMesh { return models.get(self.model as usize).unwrap().face_mesh(self.face) } pub fn normal(&self,models:&Vec) -> glam::Vec3 { return models.get(self.model as usize).unwrap().face_normal(self.face) } } pub type TIME = i64; const CONTROL_JUMP:u32 = 0b01000000;//temp impl PhysicsState { //delete this, we are tickless gamers pub fn run(&mut self, time: TIME, control_dir: glam::Vec3, controls: u32){ let target_tick = (time*self.strafe_tick_num/self.strafe_tick_den) as u32; //the game code can run for 1 month before running out of ticks while self.tick glam::Vec3 { let dt=(time-self.body.time) as f64/1_000_000_000f64; self.body.position+self.body.velocity*(dt as f32)+self.gravity*((0.5*dt*dt) as f32) } fn next_strafe_event(&self) -> Option { return Some(EventStruct{ time:(self.time*self.strafe_tick_num/self.strafe_tick_den+1)*self.strafe_tick_den/self.strafe_tick_num, event:crate::event::EventEnum::StrafeTick }); } fn next_walk_event(&self) -> Option { //check if you are accelerating towards a walk target velocity and create an event return None; } } impl crate::event::EventTrait for PhysicsState { //this little next event function can cache its return value and invalidate the cached value by watching the State. fn next_event(&self) -> Option { //JUST POLLING!!! NO MUTATION let mut best = crate::event::EventCollector::new(); //autohop (already pressing spacebar; the signal to begin trying to jump is different) if self.grounded&&self.jump_trying { //scroll will be implemented with InputEvent::Jump(true) but it blocks setting self.jump_trying=true best.collect(Some(EventStruct{ time:self.time, event:crate::event::EventEnum::Jump })); } //check for collision stop events with curent contacts for collision_data in self.contacts.iter() { best.collect(self.predict_collision(collision_data.model)); } //check for collision start events (against every part in the game with no optimization!!) for &model in self.world.models { best.collect(self.predict_collision(&model)); if self.grounded { //walk maintenance best.collect(self.next_walk_event()); }else{ //check to see when the next strafe tick is best.collect(self.next_strafe_event()); } best.event() } }