refactor JumpCalculation

This commit is contained in:
Quaternions 2024-08-07 14:44:24 -07:00
parent eebde9b54a
commit 22216846e3
2 changed files with 145 additions and 43 deletions

View File

@ -31,6 +31,22 @@ pub enum Booster{
//Affine(crate::integer::Planar64Affine3),//capable of SetVelocity,DotVelocity,normal booster,bouncy part,redirect velocity, and much more //Affine(crate::integer::Planar64Affine3),//capable of SetVelocity,DotVelocity,normal booster,bouncy part,redirect velocity, and much more
Velocity(Planar64Vec3),//straight up boost velocity adds to your current velocity Velocity(Planar64Vec3),//straight up boost velocity adds to your current velocity
Energy{direction:Planar64Vec3,energy:Planar64},//increase energy in direction Energy{direction:Planar64Vec3,energy:Planar64},//increase energy in direction
AirTime(Time),//increase airtime, invariant across mass and gravity changes
Height(Planar64),//increase height, invariant across mass and gravity changes
}
impl Booster{
pub fn boost(&self,velocity:Planar64Vec3)->Planar64Vec3{
match self{
&Booster::Velocity(boost_velocity)=>velocity+boost_velocity,
&Booster::Energy{direction,energy}=>{
let d=direction.dot(velocity);
//TODO: think about negative
velocity+direction.with_length((d*d+energy).sqrt()-d)
},
Booster::AirTime(_)=>todo!(),
Booster::Height(_)=>todo!(),
}
}
} }
#[derive(Clone,Hash,Eq,PartialEq)] #[derive(Clone,Hash,Eq,PartialEq)]
pub enum TrajectoryChoice{ pub enum TrajectoryChoice{

View File

@ -41,33 +41,135 @@ impl std::default::Default for StyleModifiers{
#[derive(Clone,Debug)] #[derive(Clone,Debug)]
pub enum JumpCalculation{ pub enum JumpCalculation{
Capped,//roblox Max,//Roblox: jumped_speed=max(velocity.boost(),velocity.jump())
Energy,//new BoostThenJump,//jumped_speed=velocity.boost().jump()
Linear,//source JumpThenBoost,//jumped_speed=velocity.jump().boost()
} }
#[derive(Clone,Debug)] #[derive(Clone,Debug)]
pub enum JumpImpulse{ pub enum JumpImpulse{
FromTime(Time),//jump time is invariant across mass and gravity changes Time(Time),//jump time is invariant across mass and gravity changes
FromHeight(Planar64),//jump height is invariant across mass and gravity changes Height(Planar64),//jump height is invariant across mass and gravity changes
FromLinear(Planar64),//jump velocity is invariant across mass and gravity changes Linear(Planar64),//jump velocity is invariant across mass and gravity changes
FromEnergy(Planar64),// :) Energy(Planar64),// :)
} }
//Jumping acts on dot(walks_state.normal,body.velocity) //Jumping acts on dot(walks_state.normal,body.velocity)
//Capped means it increases the dot to the cap
//Energy means it adds energy //Energy means it adds energy
//Linear means it linearly adds on //Linear means it linearly adds on
impl JumpImpulse{ impl JumpImpulse{
//fn get_jump_time(&self)->Planar64 pub fn jump(
//fn get_jump_height(&self)->Planar64 &self,
//fn get_jump_energy(&self)->Planar64 velocity:Planar64Vec3,
jump_dir:Planar64Vec3,
gravity:&Planar64Vec3,
mass:Planar64,
)->Planar64Vec3{
match self{
&JumpImpulse::Time(time)=>velocity-*gravity*time,
&JumpImpulse::Height(height)=>{
//height==-v.y*v.y/(2*g.y);
//use energy to determine max height
let g=gravity.length();
let v_g=gravity.dot(velocity)/g;
//do it backwards
velocity-gravity.with_length((v_g*v_g+height*g*2).sqrt()+v_g)
},
&JumpImpulse::Linear(jump_speed)=>velocity+jump_dir.with_length(jump_speed),
&JumpImpulse::Energy(energy)=>{
//calculate energy
let e=gravity.dot(velocity);
//add
//you get the idea
todo!()
},
}
}
//TODO: remove this and implement JumpCalculation properly
pub fn get_jump_deltav(&self,gravity:&Planar64Vec3,mass:Planar64)->Planar64{ pub fn get_jump_deltav(&self,gravity:&Planar64Vec3,mass:Planar64)->Planar64{
//gravity.length() is actually the proper calculation because the jump is always opposite the gravity direction //gravity.length() is actually the proper calculation because the jump is always opposite the gravity direction
match self{ match self{
&JumpImpulse::FromTime(time)=>gravity.length()*(time/2), &JumpImpulse::Time(time)=>gravity.length()*(time/2),
&JumpImpulse::FromHeight(height)=>(gravity.length()*height*2).sqrt(), &JumpImpulse::Height(height)=>(gravity.length()*height*2).sqrt(),
&JumpImpulse::FromLinear(deltav)=>deltav, &JumpImpulse::Linear(deltav)=>deltav,
&JumpImpulse::FromEnergy(energy)=>(energy*2/mass).sqrt(), &JumpImpulse::Energy(energy)=>(energy*2/mass).sqrt(),
}
}
}
#[derive(Clone,Debug)]
pub struct JumpSettings{
//information used to calculate jump power
pub impulse:JumpImpulse,
//information used to calculate jump behaviour
pub calculation:JumpCalculation,
//limit the minimum jump power when combined with downwards momentum
//This is true in both roblox and source
pub limit_minimum:bool,
}
impl JumpSettings{
pub fn jumped_velocity(
&self,
style:&StyleModifiers,
jump_dir:Planar64Vec3,
rel_velocity:Planar64Vec3,
booster:Option<&crate::gameplay_attributes::Booster>,
)->Planar64Vec3{
let jump_speed=self.impulse.get_jump_deltav(&style.gravity,style.mass);
match (self.limit_minimum,&self.calculation){
(true,JumpCalculation::Max)=>{
//the roblox calculation
let boost_vel=match booster{
Some(booster)=>booster.boost(rel_velocity),
None=>rel_velocity,
};
let j=boost_vel.dot(jump_dir);
if j<jump_speed{
//weak booster: just do a regular jump
boost_vel+jump_dir.with_length(jump_speed-j)
}else{
//activate booster normally, jump does nothing
boost_vel
}
},
(true,_)=>{
//the source calculation (?)
let boost_vel=match booster{
Some(booster)=>booster.boost(rel_velocity),
None=>rel_velocity,
};
let j=boost_vel.dot(jump_dir);
if j<jump_speed{
//speed in direction of jump cannot be lower than amount
boost_vel+jump_dir.with_length(jump_speed-j)
}else{
//boost and jump add together
boost_vel+jump_dir.with_length(jump_speed)
}
}
(false,JumpCalculation::Max)=>{
//??? calculation
//max(boost_vel,jump_vel)
let boost_vel=match booster{
Some(booster)=>booster.boost(rel_velocity),
None=>rel_velocity,
};
let boost_dot=boost_vel.dot(jump_dir);
if boost_dot<jump_speed{
//weak boost is extended to jump speed
boost_vel+jump_dir.with_length(jump_speed-boost_dot)
}else{
//activate booster normally, jump does nothing
boost_vel
}
},
//the strafe client calculation
(false,_)=>{
let boost_vel=match booster{
Some(booster)=>booster.boost(rel_velocity),
None=>rel_velocity,
};
boost_vel+jump_dir.with_length(jump_speed)
},
} }
} }
} }
@ -185,26 +287,6 @@ impl PropulsionSettings{
} }
} }
#[derive(Clone,Debug)]
pub struct JumpSettings{
//information used to calculate jump power
pub impulse:JumpImpulse,
//information used to calculate jump behaviour
pub calculation:JumpCalculation,
}
impl JumpSettings{
pub fn jumped_velocity(&self,style:&StyleModifiers,jump_dir:Planar64Vec3,velocity:Planar64Vec3)->Planar64Vec3{
match self.calculation{
//roblox style
JumpCalculation::Capped=>todo!(),
//something different
JumpCalculation::Energy=>todo!(),
//source style
JumpCalculation::Linear=>velocity+jump_dir*(self.impulse.get_jump_deltav(&style.gravity,style.mass)/jump_dir.length()),
}
}
}
#[derive(Clone,Debug)] #[derive(Clone,Debug)]
pub struct AccelerateSettings{ pub struct AccelerateSettings{
pub accel:Planar64, pub accel:Planar64,
@ -345,8 +427,9 @@ impl StyleModifiers{
tick_rate:Ratio64::new(64,Time::ONE_SECOND.nanos() as u64).unwrap(), tick_rate:Ratio64::new(64,Time::ONE_SECOND.nanos() as u64).unwrap(),
}), }),
jump:Some(JumpSettings{ jump:Some(JumpSettings{
impulse:JumpImpulse::FromEnergy(Planar64::int(512)), impulse:JumpImpulse::Energy(Planar64::int(512)),
calculation:JumpCalculation::Energy, calculation:JumpCalculation::JumpThenBoost,
limit_minimum:false,
}), }),
gravity:Planar64Vec3::int(0,-80,0), gravity:Planar64Vec3::int(0,-80,0),
mass:Planar64::int(1), mass:Planar64::int(1),
@ -386,8 +469,9 @@ impl StyleModifiers{
tick_rate:Ratio64::new(100,Time::ONE_SECOND.nanos() as u64).unwrap(), tick_rate:Ratio64::new(100,Time::ONE_SECOND.nanos() as u64).unwrap(),
}), }),
jump:Some(JumpSettings{ jump:Some(JumpSettings{
impulse:JumpImpulse::FromTime(Time::from_micros(715_588)), impulse:JumpImpulse::Time(Time::from_micros(715_588)),
calculation:JumpCalculation::Linear,//Should be capped calculation:JumpCalculation::Max,
limit_minimum:true,
}), }),
gravity:Planar64Vec3::int(0,-100,0), gravity:Planar64Vec3::int(0,-100,0),
mass:Planar64::int(1), mass:Planar64::int(1),
@ -442,8 +526,9 @@ impl StyleModifiers{
tick_rate:Ratio64::new(100,Time::ONE_SECOND.nanos() as u64).unwrap(), tick_rate:Ratio64::new(100,Time::ONE_SECOND.nanos() as u64).unwrap(),
}), }),
jump:Some(JumpSettings{ jump:Some(JumpSettings{
impulse:JumpImpulse::FromHeight(Planar64::int(52)*VALVE_SCALE), impulse:JumpImpulse::Height(Planar64::int(52)*VALVE_SCALE),
calculation:JumpCalculation::Linear, calculation:JumpCalculation::JumpThenBoost,
limit_minimum:true,
}), }),
gravity:Planar64Vec3::int(0,-800,0)*VALVE_SCALE, gravity:Planar64Vec3::int(0,-800,0)*VALVE_SCALE,
mass:Planar64::int(1), mass:Planar64::int(1),
@ -482,8 +567,9 @@ impl StyleModifiers{
tick_rate:Ratio64::new(66,Time::ONE_SECOND.nanos() as u64).unwrap(), tick_rate:Ratio64::new(66,Time::ONE_SECOND.nanos() as u64).unwrap(),
}), }),
jump:Some(JumpSettings{ jump:Some(JumpSettings{
impulse:JumpImpulse::FromHeight(Planar64::int(52)*VALVE_SCALE), impulse:JumpImpulse::Height(Planar64::int(52)*VALVE_SCALE),
calculation:JumpCalculation::Linear, calculation:JumpCalculation::JumpThenBoost,
limit_minimum:true,
}), }),
gravity:Planar64Vec3::int(0,-800,0)*VALVE_SCALE, gravity:Planar64Vec3::int(0,-800,0)*VALVE_SCALE,
mass:Planar64::int(1), mass:Planar64::int(1),