Compare commits

...

2 Commits

Author SHA1 Message Date
53d2b5b3f5 wip: timelines 2023-09-08 23:20:27 -07:00
c565120ea7 wip: tickless physics 2023-09-08 20:18:31 -07:00
3 changed files with 93 additions and 34 deletions

View File

@ -5,6 +5,8 @@ pub enum PhysicsInstruction {
CollisionEnd(RelativeCollision), CollisionEnd(RelativeCollision),
StrafeTick, StrafeTick,
Jump, Jump,
SetWalkTargetVelocity(glam::Vec3),
ReachWalkTargetVelocity,
// Water, // Water,
// Spawn( // Spawn(
// Option<SpawnId>, // Option<SpawnId>,
@ -19,6 +21,13 @@ pub struct Body {
pub time: TIME,//nanoseconds x xxxxD! pub time: TIME,//nanoseconds x xxxxD!
} }
pub enum MoveRestriction {
Air,
Water,
Ground,
Ladder,//multiple ladders how
}
pub struct PhysicsState { pub struct PhysicsState {
pub body: Body, pub body: Body,
pub contacts: Vec<RelativeCollision>, pub contacts: Vec<RelativeCollision>,
@ -176,41 +185,19 @@ pub type TIME = i64;
const CONTROL_JUMP:u32 = 0b01000000;//temp DATA NORMALIZATION!@#$ const CONTROL_JUMP:u32 = 0b01000000;//temp DATA NORMALIZATION!@#$
impl PhysicsState { impl PhysicsState {
//delete this, we are tickless gamers //delete this, we are tickless gamers
pub fn run(&mut self, time: TIME, control_dir: glam::Vec3, controls: u32){ pub fn run(&mut self, time: TIME){
let target_tick = (time*self.strafe_tick_num/self.strafe_tick_den) as u32; //prepare is ommitted - everything is done via instructions.
//the game code can run for 1 month before running out of ticks while let Some(instruction) = self.next_instruction() {//collect
while self.tick<target_tick { if time<instruction.time {
self.tick += 1; break;
let dt=0.01;
let d=self.body.velocity.dot(control_dir);
if d<self.mv {
self.body.velocity+=(self.mv-d)*control_dir;
}
self.body.velocity+=self.gravity*dt;
self.body.position+=self.body.velocity*dt;
if self.body.position.y<0.0{
self.body.position.y=0.0;
self.body.velocity.y=0.0;
self.grounded=true;
}
if self.grounded&&(controls&CONTROL_JUMP)!=0 {
self.grounded=false;
self.body.velocity+=glam::Vec3::new(0.0,0.715588/2.0*100.0,0.0);
}
if self.grounded {
let applied_friction=self.friction*dt;
let targetv=control_dir*self.walkspeed;
let diffv=targetv-self.body.velocity;
if applied_friction*applied_friction<diffv.length_squared() {
self.body.velocity+=applied_friction*diffv.normalize();
} else {
//PhysicsInstruction::WalkTargetReached
self.body.velocity=targetv;
}
} }
//advance
self.advance_time(instruction.time);
//process
self.process_instruction(instruction);
//write hash lol
} }
self.body.time=target_tick as TIME*self.strafe_tick_den/self.strafe_tick_num;
} }
//delete this //delete this
@ -304,7 +291,31 @@ impl crate::instruction::InstructionEmitter<PhysicsInstruction> for PhysicsState
} }
impl crate::instruction::InstructionConsumer<PhysicsInstruction> for PhysicsState { impl crate::instruction::InstructionConsumer<PhysicsInstruction> for PhysicsState {
fn process_instruction(&mut self, instruction:TimedInstruction<PhysicsInstruction>) { fn process_instruction(&mut self, ins:TimedInstruction<PhysicsInstruction>) {
// //mutate position and velocity and time
self.body.advance_time(ins.time);//should this be in a separate function: self.advance_time?
match ins.instruction {
PhysicsInstruction::CollisionStart(_) => todo!(),
PhysicsInstruction::CollisionEnd(_) => todo!(),
PhysicsInstruction::StrafeTick => {
let control_dir=self.get_control_dir();//this respects your mouse interpolation settings
let d=self.body.velocity.dot(control_dir);
if d<self.mv {
self.body.velocity+=(self.mv-d)*control_dir;
}
}
PhysicsInstruction::Jump => {
self.grounded=false;//do I need this?
self.body.velocity+=glam::Vec3::new(0.0,0.715588/2.0*100.0,0.0);
}
PhysicsInstruction::ReachWalkTargetVelocity => {
//precisely set velocity
self.body.velocity=self.walk_target_velocity;
}
PhysicsInstruction::SetWalkTargetVelocity(v) => {
self.walk_target_velocity=v;
//calculate acceleration yada yada
},
}
} }
} }

View File

@ -1,3 +1,4 @@
pub mod framework; pub mod framework;
pub mod body; pub mod body;
pub mod instruction; pub mod instruction;
pub mod timelines;

47
src/timelines.rs Normal file
View File

@ -0,0 +1,47 @@
type ORDER = u32;
pub struct Tracker {
order: ORDER,
}
pub struct TimelineInstruction<I>{
pub order: ORDER,//absolute ordering of instructions which can be used for sorting even when there are multiple simultaneous timestamps
pub instruction: crate::instruction::TimedInstruction<I>,
}
pub struct Timeline<I>{
instructions: std::collections::VecDeque<TimelineInstruction<I>>,
trackers: Vec<Tracker>,//wrong
}
impl<I> Timeline<I>{
pub fn new() -> Self {
Self{
instructions:std::collections::VecDeque::<TimelineInstruction<I>>::new(),
trackers:Vec::<Tracker>::new(),
}
}
pub fn len(&self) -> usize {
return self.instructions.len()
}
pub fn first(&self) -> Option<&TimelineInstruction<I>> {
return self.instructions.get(0)
}
pub fn last(&self) -> Option<&TimelineInstruction<I>> {
return self.instructions.get(self.instructions.len()-1)
}
pub fn append(&mut self,instruction:TimelineInstruction<I>){
let i=self.instructions.len();
self.instructions.push_back(instruction);
for tracker in self.trackers.iter() {
tracker.set_active(true);
}
}
pub fn get_index_after_time(&mut self,time:crate::body::TIME) -> usize{
self.instructions.partition_point(|ins|ins.instruction.time<time)
}
pub fn get_index_after_order(&mut self,order:ORDER) -> usize{
self.instructions.partition_point(|ins|ins.order<order)
}
}