forked from StrafesNET/strafe-client
wip
This commit is contained in:
parent
c895a66ad6
commit
dbd08729d7
204
src/physics.rs
204
src/physics.rs
@ -138,59 +138,61 @@ impl JumpDirection{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
enum WalkEnum{
|
enum WalkTarget{
|
||||||
Reached,
|
Reached,
|
||||||
Transient(WalkTarget),
|
Reachable{
|
||||||
}
|
acceleration:Planar64Vec3,
|
||||||
struct WalkTarget{
|
|
||||||
velocity:Planar64Vec3,
|
|
||||||
time:Time,
|
time:Time,
|
||||||
|
},
|
||||||
|
//walk target will never be reached
|
||||||
|
Unreachable{
|
||||||
|
acceleration:Planar64Vec3,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
struct WalkState{
|
struct WalkState{
|
||||||
jump_direction:JumpDirection,
|
jump_direction:JumpDirection,
|
||||||
contact:ContactCollision,
|
contact:ContactCollision,
|
||||||
state:WalkEnum,
|
target:WalkTarget,
|
||||||
}
|
}
|
||||||
impl WalkEnum{
|
impl WalkTarget{
|
||||||
//args going crazy
|
fn with_target_diff(target_diff:Planar64Vec3,accel:Planar64,time:Time)->Self{
|
||||||
//(walk_enum,body.acceleration)=with_target_velocity();
|
|
||||||
fn with_target_velocity(body:&Body,style:&StyleModifiers,velocity:Planar64Vec3,normal:&Planar64Vec3,speed:Planar64,normal_accel:Planar64)->(WalkEnum,Planar64Vec3){
|
|
||||||
let mut target_diff=velocity-body.velocity;
|
|
||||||
//remove normal component
|
|
||||||
target_diff-=normal.clone()*(normal.dot(target_diff)/normal.dot(normal.clone()));
|
|
||||||
if target_diff==Planar64Vec3::ZERO{
|
if target_diff==Planar64Vec3::ZERO{
|
||||||
(WalkEnum::Reached,Planar64Vec3::ZERO)
|
WalkTarget::Reached
|
||||||
}else{
|
}else{
|
||||||
//normal friction acceleration is clippedAcceleration.dot(normal)*friction
|
//normal friction acceleration is clippedAcceleration.dot(normal)*friction
|
||||||
let diff_len=target_diff.length();
|
WalkTarget::Reachable{
|
||||||
let friction=if diff_len<speed{
|
acceleration:target_diff.with_length(accel),
|
||||||
style.static_friction
|
time:time+Time::from(target_diff.length()/accel)
|
||||||
}else{
|
}
|
||||||
style.kinetic_friction
|
}
|
||||||
};
|
}
|
||||||
let accel=style.walk_accel.min(normal_accel*friction);
|
fn acceleration(&self)->Planar64Vec3{
|
||||||
let time_delta=diff_len/accel;
|
match self{
|
||||||
let a=target_diff.with_length(accel);
|
WalkTarget::Reached=>Planar64Vec3::ZERO,
|
||||||
(WalkEnum::Transient(WalkTarget{velocity,time:body.time+Time::from(time_delta)}),a)
|
&WalkTarget::Reachable{acceleration,time:_}=>acceleration,
|
||||||
|
&WalkTarget::Unreachable{acceleration}=>acceleration,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl WalkState{
|
impl WalkState{
|
||||||
fn ground(body:&Body,style:&StyleModifiers,gravity:Planar64Vec3,velocity:Planar64Vec3,contact:ContactCollision,normal:&Planar64Vec3)->(Self,Planar64Vec3){
|
fn ground(body:&Body,walk_settings:&gameplay_style::WalkSettings,gravity:Planar64Vec3,velocity:Planar64Vec3,contact:ContactCollision,normal:Planar64Vec3)->Self{
|
||||||
let (walk_enum,a)=WalkEnum::with_target_velocity(body,style,velocity,&Planar64Vec3::Y,style.walk_speed,-normal.dot(gravity));
|
let target_diff=velocity-body.velocity;
|
||||||
(Self{
|
//precalculate accel
|
||||||
state:walk_enum,
|
let accel=walk_settings.accel(target_diff,gravity);
|
||||||
|
Self{
|
||||||
|
target:WalkTarget::with_target_diff(target_diff,accel,body.time),
|
||||||
contact,
|
contact,
|
||||||
jump_direction:JumpDirection::Exactly(Planar64Vec3::Y),
|
jump_direction:JumpDirection::Exactly(Planar64Vec3::Y),
|
||||||
},a)
|
|
||||||
}
|
}
|
||||||
fn ladder(body:&Body,style:&StyleModifiers,gravity:Planar64Vec3,velocity:Planar64Vec3,contact:ContactCollision,normal:&Planar64Vec3)->(Self,Planar64Vec3){
|
}
|
||||||
let (walk_enum,a)=WalkEnum::with_target_velocity(body,style,velocity,normal,style.ladder_speed,style.ladder_accel);
|
fn ladder(body:&Body,ladder_settings:&gameplay_style::LadderSettings,gravity:Planar64Vec3,velocity:Planar64Vec3,contact:ContactCollision,normal:Planar64Vec3)->Self{
|
||||||
(Self{
|
let target_diff=velocity-body.velocity;
|
||||||
state:walk_enum,
|
let accel=ladder_settings.accel(target_diff,gravity);
|
||||||
|
Self{//,style,velocity,normal,style.ladder_speed,style.ladder_accel
|
||||||
|
target:WalkTarget::with_target_diff(target_diff,accel,body.time),
|
||||||
contact,
|
contact,
|
||||||
jump_direction:JumpDirection::FromContactNormal,
|
jump_direction:JumpDirection::FromContactNormal,
|
||||||
},a)
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -481,6 +483,59 @@ impl MoveState{
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/// Returns whether the MoveState was changed
|
||||||
|
fn apply_input(&mut self,touching:&TouchingState,models:&PhysicsModels,hitbox_mesh:&HitboxMesh,body:&mut Body){
|
||||||
|
match self{
|
||||||
|
MoveState::Fly=>(),
|
||||||
|
MoveState::Air|MoveState::Water=>s.touching.base_acceleration(models,&s.style,&s.camera,&s.input_state),
|
||||||
|
MoveState::Walk(WalkState{target: state,contact,jump_direction:_})=>{
|
||||||
|
let n=contact_normal(models,hitbox_mesh,contact);
|
||||||
|
let gravity=s.touching.base_acceleration(models,&s.style,&s.camera,&s.input_state);
|
||||||
|
let a;
|
||||||
|
let mut v=s.style.get_walk_target_velocity(&s.camera,&s.input_state,&n);
|
||||||
|
s.touching.constrain_velocity(models,hitbox_mesh,&mut v);
|
||||||
|
let normal_accel=-n.dot(gravity)/n.length();
|
||||||
|
(*state,a)=WalkTarget::with_target_velocity(&s.body,&s.style,v,&n,s.style.walk_speed,normal_accel);
|
||||||
|
a
|
||||||
|
},
|
||||||
|
MoveState::Ladder(WalkState{target: state,contact,jump_direction:_})=>{
|
||||||
|
let n=contact_normal(models,hitbox_mesh,contact);
|
||||||
|
//let gravity=s.touching.base_acceleration(&data.models,&s.style,&s.camera,s.controls,&s.next_mouse,s.time);
|
||||||
|
let a;
|
||||||
|
let mut v=s.style.get_ladder_target_velocity(&s.camera,&s.input_state,&n);
|
||||||
|
s.touching.constrain_velocity(models,hitbox_mesh,&mut v);
|
||||||
|
(*state,a)=WalkTarget::with_target_velocity(&s.body,&s.style,v,&n,s.style.ladder_speed,s.style.ladder_accel);
|
||||||
|
a
|
||||||
|
},
|
||||||
|
}
|
||||||
|
self.apply_to_body(touching,models,hitbox_mesh,body);
|
||||||
|
}
|
||||||
|
fn get_walk_state(&self)->Option<&WalkState>{
|
||||||
|
match self{
|
||||||
|
MoveState::Walk(walk_state)
|
||||||
|
|MoveState::Ladder(walk_state)
|
||||||
|
=>Some(walk_state),
|
||||||
|
MoveState::Air
|
||||||
|
|MoveState::Water
|
||||||
|
|MoveState::Fly
|
||||||
|
=>None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn next_move_instruction(&self)->Option<TimedInstruction<PhysicsInstruction>>{
|
||||||
|
//check if you have a valid walk state and create an instruction
|
||||||
|
match self{
|
||||||
|
MoveState::Walk(walk_state)|MoveState::Ladder(walk_state)=>match &walk_state.target{
|
||||||
|
WalkTarget::Reachable(walk_target)=>Some(TimedInstruction{
|
||||||
|
time:walk_target.time,
|
||||||
|
instruction:PhysicsInstruction::ReachWalkTargetVelocity
|
||||||
|
}),
|
||||||
|
WalkTarget::Reached=>None,
|
||||||
|
}
|
||||||
|
MoveState::Air=>self.next_strafe_instruction(),
|
||||||
|
MoveState::Water=>None,//TODO
|
||||||
|
MoveState::Fly=>None,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone,Default)]
|
#[derive(Clone,Default)]
|
||||||
@ -620,9 +675,7 @@ impl TouchingState{
|
|||||||
fn base_acceleration(&self,models:&PhysicsModels,style:&StyleModifiers,camera:&PhysicsCamera,input_state:&InputState)->Planar64Vec3{
|
fn base_acceleration(&self,models:&PhysicsModels,style:&StyleModifiers,camera:&PhysicsCamera,input_state:&InputState)->Planar64Vec3{
|
||||||
let mut a=style.gravity;
|
let mut a=style.gravity;
|
||||||
if let Some(rocket_settings)=style.rocket{
|
if let Some(rocket_settings)=style.rocket{
|
||||||
if rocket_settings.activates(input_state.controls){
|
a+=rocket_settings.acceleration(style.get_propulsion_control_dir(camera,input_state.controls));
|
||||||
a+=rocket_settings.acceleration(style.get_propulsion_control_dir(camera,input_state));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
//add accelerators
|
//add accelerators
|
||||||
for contact in &self.contacts{
|
for contact in &self.contacts{
|
||||||
@ -647,7 +700,7 @@ impl TouchingState{
|
|||||||
_=>panic!("impossible touching state"),
|
_=>panic!("impossible touching state"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//add water../?
|
//TODO: add water
|
||||||
a
|
a
|
||||||
}
|
}
|
||||||
fn constrain_velocity(&self,models:&PhysicsModels,hitbox_mesh:&HitboxMesh,velocity:&mut Planar64Vec3){
|
fn constrain_velocity(&self,models:&PhysicsModels,hitbox_mesh:&HitboxMesh,velocity:&mut Planar64Vec3){
|
||||||
@ -954,23 +1007,8 @@ impl PhysicsState {
|
|||||||
// instruction:PhysicsInstruction::Water
|
// instruction:PhysicsInstruction::Water
|
||||||
// });
|
// });
|
||||||
// }
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
fn next_move_instruction(&self)->Option<TimedInstruction<PhysicsInstruction>>{
|
|
||||||
//check if you have a valid walk state and create an instruction
|
|
||||||
match &self.move_state{
|
|
||||||
MoveState::Walk(walk_state)|MoveState::Ladder(walk_state)=>match &walk_state.state{
|
|
||||||
WalkEnum::Transient(walk_target)=>Some(TimedInstruction{
|
|
||||||
time:walk_target.time,
|
|
||||||
instruction:PhysicsInstruction::ReachWalkTargetVelocity
|
|
||||||
}),
|
|
||||||
WalkEnum::Reached=>None,
|
|
||||||
}
|
|
||||||
MoveState::Air=>self.next_strafe_instruction(),
|
|
||||||
MoveState::Water=>None,//TODO
|
|
||||||
MoveState::Fly=>None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct PhysicsContext{
|
pub struct PhysicsContext{
|
||||||
pub state:PhysicsState,//this captures the entire state of the physics.
|
pub state:PhysicsState,//this captures the entire state of the physics.
|
||||||
@ -1074,33 +1112,6 @@ impl PhysicsContext{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO get rid of this trash
|
|
||||||
fn refresh_walk_target(s:&mut PhysicsState,data:&PhysicsData)->Planar64Vec3{
|
|
||||||
match &mut s.move_state{
|
|
||||||
MoveState::Fly=>Planar64Vec3::ZERO,
|
|
||||||
MoveState::Air|MoveState::Water=>s.touching.base_acceleration(&data.models,&s.style,&s.camera,&s.input_state),
|
|
||||||
MoveState::Walk(WalkState{state,contact,jump_direction:_})=>{
|
|
||||||
let n=contact_normal(&data.models,&data.hitbox_mesh,contact);
|
|
||||||
let gravity=s.touching.base_acceleration(&data.models,&s.style,&s.camera,&s.input_state);
|
|
||||||
let a;
|
|
||||||
let mut v=s.style.get_walk_target_velocity(&s.camera,&s.input_state,&n);
|
|
||||||
s.touching.constrain_velocity(&data.models,&data.hitbox_mesh,&mut v);
|
|
||||||
let normal_accel=-n.dot(gravity)/n.length();
|
|
||||||
(*state,a)=WalkEnum::with_target_velocity(&s.body,&s.style,v,&n,s.style.walk_speed,normal_accel);
|
|
||||||
a
|
|
||||||
},
|
|
||||||
MoveState::Ladder(WalkState{state,contact,jump_direction:_})=>{
|
|
||||||
let n=contact_normal(&data.models,&data.hitbox_mesh,contact);
|
|
||||||
//let gravity=s.touching.base_acceleration(&data.models,&s.style,&s.camera,s.controls,&s.next_mouse,s.time);
|
|
||||||
let a;
|
|
||||||
let mut v=s.style.get_ladder_target_velocity(&s.camera,&s.input_state,&n);
|
|
||||||
s.touching.constrain_velocity(&data.models,&data.hitbox_mesh,&mut v);
|
|
||||||
(*state,a)=WalkEnum::with_target_velocity(&s.body,&s.style,v,&n,s.style.ladder_speed,s.style.ladder_accel);
|
|
||||||
a
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn literally_next_instruction_but_with_context(state:&PhysicsState,data:&PhysicsData,time_limit:Time)->Option<TimedInstruction<PhysicsInstruction>>{
|
fn literally_next_instruction_but_with_context(state:&PhysicsState,data:&PhysicsData,time_limit:Time)->Option<TimedInstruction<PhysicsInstruction>>{
|
||||||
//JUST POLLING!!! NO MUTATION
|
//JUST POLLING!!! NO MUTATION
|
||||||
let mut collector = instruction::InstructionCollector::new(time_limit);
|
let mut collector = instruction::InstructionCollector::new(time_limit);
|
||||||
@ -1132,17 +1143,6 @@ impl PhysicsContext{
|
|||||||
collector.instruction()
|
collector.instruction()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_walk_state(move_state:&MoveState)->Option<&WalkState>{
|
|
||||||
match move_state{
|
|
||||||
MoveState::Walk(walk_state)
|
|
||||||
|MoveState::Ladder(walk_state)
|
|
||||||
=>Some(walk_state),
|
|
||||||
MoveState::Air
|
|
||||||
|MoveState::Water
|
|
||||||
|MoveState::Fly
|
|
||||||
=>None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn contact_normal(models:&PhysicsModels,hitbox_mesh:&HitboxMesh,contact:&ContactCollision)->Planar64Vec3{
|
fn contact_normal(models:&PhysicsModels,hitbox_mesh:&HitboxMesh,contact:&ContactCollision)->Planar64Vec3{
|
||||||
let model_mesh=models.mesh(contact.convex_mesh_id);
|
let model_mesh=models.mesh(contact.convex_mesh_id);
|
||||||
@ -1350,7 +1350,7 @@ fn run_teleport_behaviour(wormhole:&Option<gameplay_attributes::Wormhole>,models
|
|||||||
}
|
}
|
||||||
let calc_move=if state.style.get_control(Controls::Jump,state.input_state.controls){
|
let calc_move=if state.style.get_control(Controls::Jump,state.input_state.controls){
|
||||||
state.style.jump.is_some_and(|jump_settings|{
|
state.style.jump.is_some_and(|jump_settings|{
|
||||||
get_walk_state(&state.move_state).is_some_and(|walk_state|{
|
state.move_state.get_walk_state().is_some_and(|walk_state|{
|
||||||
let jump_dir=walk_state.jump_direction.direction(&data.models,&data.hitbox_mesh,&walk_state.contact);
|
let jump_dir=walk_state.jump_direction.direction(&data.models,&data.hitbox_mesh,&walk_state.contact);
|
||||||
v=jump_settings.jumped_velocity(&state.style,jump_dir,v);
|
v=jump_settings.jumped_velocity(&state.style,jump_dir,v);
|
||||||
set_velocity_cull(&mut state.body,&mut state.touching,&data.models,&data.hitbox_mesh,v)
|
set_velocity_cull(&mut state.body,&mut state.touching,&data.models,&data.hitbox_mesh,v)
|
||||||
@ -1375,8 +1375,9 @@ fn run_teleport_behaviour(wormhole:&Option<gameplay_attributes::Wormhole>,models
|
|||||||
if calc_move||Planar64::ZERO<normal.dot(v){
|
if calc_move||Planar64::ZERO<normal.dot(v){
|
||||||
(state.move_state,state.body.acceleration)=state.touching.get_move_state(&state.body,&data.models,&state.style,&data.hitbox_mesh,&state.camera,&state.input_state,state.time);
|
(state.move_state,state.body.acceleration)=state.touching.get_move_state(&state.body,&data.models,&state.style,&data.hitbox_mesh,&state.camera,&state.input_state,state.time);
|
||||||
}
|
}
|
||||||
let a=refresh_walk_target(state,data);
|
if state.move_state.apply_input(){
|
||||||
set_acceleration(&mut state.body,&state.touching,&data.models,&data.hitbox_mesh,a);
|
state.move_state.apply_to_body(&mut state.body,&state.touching,&data.models,&data.hitbox_mesh,a);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
(PhysicsCollisionAttributes::Intersect{intersecting: _,general},Collision::Intersect(intersect))=>{
|
(PhysicsCollisionAttributes::Intersect{intersecting: _,general},Collision::Intersect(intersect))=>{
|
||||||
//I think that setting the velocity to 0 was preventing surface contacts from entering an infinite loop
|
//I think that setting the velocity to 0 was preventing surface contacts from entering an infinite loop
|
||||||
@ -1427,15 +1428,15 @@ fn run_teleport_behaviour(wormhole:&Option<gameplay_attributes::Wormhole>,models
|
|||||||
|MoveState::Fly
|
|MoveState::Fly
|
||||||
=>println!("ReachWalkTargetVelocity fired for non-walking MoveState"),
|
=>println!("ReachWalkTargetVelocity fired for non-walking MoveState"),
|
||||||
MoveState::Walk(walk_state)|MoveState::Ladder(walk_state)=>{
|
MoveState::Walk(walk_state)|MoveState::Ladder(walk_state)=>{
|
||||||
match &mut walk_state.state{
|
match &mut walk_state.target{
|
||||||
WalkEnum::Reached=>(),
|
WalkTarget::Reached=>(),
|
||||||
WalkEnum::Transient(walk_target)=>{
|
WalkTarget::Reachable(walk_target)=>{
|
||||||
//precisely set velocity
|
//precisely set velocity
|
||||||
let a=Planar64Vec3::ZERO;//ignore gravity for now.
|
let a=Planar64Vec3::ZERO;//ignore gravity for now.
|
||||||
set_acceleration(&mut state.body,&state.touching,&data.models,&data.hitbox_mesh,a);
|
set_acceleration(&mut state.body,&state.touching,&data.models,&data.hitbox_mesh,a);
|
||||||
let v=walk_target.velocity;
|
let v=walk_target.velocity;
|
||||||
set_velocity(&mut state.body,&state.touching,&data.models,&data.hitbox_mesh,v);
|
set_velocity(&mut state.body,&state.touching,&data.models,&data.hitbox_mesh,v);
|
||||||
walk_state.state=WalkEnum::Reached;
|
walk_state.target=WalkTarget::Reached;
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1491,10 +1492,7 @@ fn run_teleport_behaviour(wormhole:&Option<gameplay_attributes::Wormhole>,models
|
|||||||
PhysicsInputInstruction::Idle=>{b_refresh_walk_target=false;},//literally idle!
|
PhysicsInputInstruction::Idle=>{b_refresh_walk_target=false;},//literally idle!
|
||||||
}
|
}
|
||||||
if b_refresh_walk_target{
|
if b_refresh_walk_target{
|
||||||
let a=refresh_walk_target(state,data);
|
state.move_state.apply_input(&mut state.body);
|
||||||
if set_acceleration_cull(&mut state.body,&mut state.touching,&data.models,&data.hitbox_mesh,a){
|
|
||||||
(state.move_state,state.body.acceleration)=state.touching.get_move_state(&state.body,&data.models,&state.style,&data.hitbox_mesh,&state.camera,&state.input_state,state.time);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user