wip: implement MoveState

This commit is contained in:
Quaternions 2023-10-12 19:44:46 -07:00
parent 87f781a656
commit cea51457a6

View File

@ -283,6 +283,13 @@ impl StyleModifiers{
} }
} }
enum MoveState{
Air,
Walk(WalkState),
Water,
Ladder(WalkState),
}
pub struct PhysicsState{ pub struct PhysicsState{
pub time:Time, pub time:Time,
pub body:Body, pub body:Body,
@ -296,8 +303,7 @@ pub struct PhysicsState{
pub camera:PhysicsCamera, pub camera:PhysicsCamera,
pub next_mouse:MouseState,//Where is the mouse headed next pub next_mouse:MouseState,//Where is the mouse headed next
pub controls:u32, pub controls:u32,
pub walk:WalkState, pub move_state:MoveState,
pub grounded:bool,
//all models //all models
pub models:Vec<ModelPhysics>, pub models:Vec<ModelPhysics>,
pub bvh:crate::bvh::BvhNode, pub bvh:crate::bvh::BvhNode,
@ -431,12 +437,11 @@ impl Default for PhysicsState{
body: Body::with_pva(Planar64Vec3::int(0,50,0),Planar64Vec3::int(0,0,0),Planar64Vec3::int(0,-100,0)), body: Body::with_pva(Planar64Vec3::int(0,50,0),Planar64Vec3::int(0,0,0),Planar64Vec3::int(0,-100,0)),
time: Time::ZERO, time: Time::ZERO,
style:StyleModifiers::default(), style:StyleModifiers::default(),
grounded: false,
contacts: std::collections::HashMap::new(), contacts: std::collections::HashMap::new(),
intersects: std::collections::HashMap::new(), intersects: std::collections::HashMap::new(),
models: Vec::new(), models: Vec::new(),
bvh:crate::bvh::BvhNode::default(), bvh:crate::bvh::BvhNode::default(),
walk: WalkState::new(), move_state: MoveState::Air,
camera: PhysicsCamera::from_offset(Planar64Vec3::int(0,2,0)),//4.5-2.5=2 camera: PhysicsCamera::from_offset(Planar64Vec3::int(0,2,0)),//4.5-2.5=2
next_mouse: MouseState::default(), next_mouse: MouseState::default(),
controls: 0, controls: 0,
@ -653,10 +658,20 @@ impl PhysicsState {
self.controls=if state{self.controls|control}else{self.controls&!control}; self.controls=if state{self.controls|control}else{self.controls&!control};
} }
fn jump(&mut self){ fn jump(&mut self){
self.grounded=false;//do I need this? match self.move_state{
let mut v=self.body.velocity+self.style.get_jump_power(); MoveState::Air=>(),
self.contact_constrain_velocity(&mut v); MoveState::Walk(walk_state)=>{
self.body.velocity=v; let mut v=self.body.velocity+self.style.get_jump_power();
self.contact_constrain_velocity(&mut v);
self.body.velocity=v;
},
MoveState::Water=>(),
MoveState::Ladder(walk_state)=>{
let mut v=self.body.velocity+self.style.get_jump_power();
self.contact_constrain_velocity(&mut v);
self.body.velocity=v;
},
}
} }
fn contact_constrain_velocity(&self,velocity:&mut Planar64Vec3){ fn contact_constrain_velocity(&self,velocity:&mut Planar64Vec3){
@ -718,43 +733,48 @@ impl PhysicsState {
fn refresh_walk_target(&mut self){ fn refresh_walk_target(&mut self){
//calculate acceleration yada yada //calculate acceleration yada yada
if self.grounded{ match self.move_state{
let mut v=self.walk.target_velocity; MoveState::Air=>(),
self.contact_constrain_velocity(&mut v); MoveState::Walk(walk_state)=>{
let mut target_diff=v-self.body.velocity; let mut v=walk_state.target_velocity;
//remove normal component self.contact_constrain_velocity(&mut v);
target_diff-=Planar64Vec3::Y*target_diff.y(); let mut target_diff=v-self.body.velocity;
if target_diff==Planar64Vec3::ZERO{ //remove normal component
let mut a=Planar64Vec3::ZERO; target_diff-=Planar64Vec3::Y*target_diff.y();
self.contact_constrain_acceleration(&mut a); if target_diff==Planar64Vec3::ZERO{
self.body.acceleration=a; let mut a=Planar64Vec3::ZERO;
self.walk.state=WalkEnum::Reached; self.contact_constrain_acceleration(&mut a);
}else{ self.body.acceleration=a;
//normal friction acceleration is clippedAcceleration.dot(normal)*friction walk_state.state=WalkEnum::Reached;
let accel=self.style.walk_accel.min(self.style.gravity.dot(Planar64Vec3::NEG_Y)*self.style.friction); }else{
let time_delta=target_diff.length()/accel; //normal friction acceleration is clippedAcceleration.dot(normal)*friction
let mut a=target_diff.with_length(accel); let accel=self.style.walk_accel.min(self.style.gravity.dot(Planar64Vec3::NEG_Y)*self.style.friction);
self.contact_constrain_acceleration(&mut a); let time_delta=target_diff.length()/accel;
self.body.acceleration=a; let mut a=target_diff.with_length(accel);
self.walk.target_time=self.body.time+Time::from(time_delta); self.contact_constrain_acceleration(&mut a);
self.walk.state=WalkEnum::Transient; self.body.acceleration=a;
} walk_state.target_time=self.body.time+Time::from(time_delta);
}else{ walk_state.state=WalkEnum::Transient;
self.walk.state=WalkEnum::Reached;//there is no walk target while not grounded }
},
MoveState::Water=>(),
MoveState::Ladder(walk_state)=>{
//
},
} }
} }
fn next_walk_instruction(&self) -> Option<TimedInstruction<PhysicsInstruction>> { fn next_move_instruction(&self)->Option<TimedInstruction<PhysicsInstruction>>{
//check if you have a valid walk state and create an instruction //check if you have a valid walk state and create an instruction
if self.grounded{ match &self.move_state{
match self.walk.state{ MoveState::Walk(walk_state)|MoveState::Ladder(walk_state)=>match &walk_state.state{
WalkEnum::Transient=>Some(TimedInstruction{ WalkEnum::Transient=>Some(TimedInstruction{
time:self.walk.target_time, time:walk_state.target_time,
instruction:PhysicsInstruction::ReachWalkTargetVelocity instruction:PhysicsInstruction::ReachWalkTargetVelocity
}), }),
WalkEnum::Reached=>None, WalkEnum::Reached=>None,
} }
}else{ MoveState::Air=>self.next_strafe_instruction(),
return None; MoveState::Water=>None,//TODO
} }
} }
fn mesh(&self) -> TreyMesh { fn mesh(&self) -> TreyMesh {
@ -1060,13 +1080,7 @@ impl crate::instruction::InstructionEmitter<PhysicsInstruction> for PhysicsState
collector.collect(self.predict_collision_start(self.time,time_limit,id)); collector.collect(self.predict_collision_start(self.time,time_limit,id));
} }
}); });
if self.grounded { collector.collect(self.next_move_instruction());
//walk maintenance
collector.collect(self.next_walk_instruction());
}else{
//check to see when the next strafe tick is
collector.collect(self.next_strafe_instruction());
}
collector.instruction() collector.instruction()
} }
} }
@ -1099,7 +1113,7 @@ impl crate::instruction::InstructionConsumer<PhysicsInstruction> for PhysicsStat
None=>match &c.face { None=>match &c.face {
TreyMeshFace::Top => { TreyMeshFace::Top => {
//ground //ground
self.grounded=true; self.move_state=MoveState::Walk(WalkState::new())
}, },
_ => (), _ => (),
}, },
@ -1124,8 +1138,7 @@ impl crate::instruction::InstructionConsumer<PhysicsInstruction> for PhysicsStat
self.contacts.clear(); self.contacts.clear();
self.intersects.clear(); self.intersects.clear();
self.body.acceleration=self.style.gravity; self.body.acceleration=self.style.gravity;
self.walk.state=WalkEnum::Reached; self.move_state=MoveState::Air;//TODO: calculate contacts and determine the actual state
self.grounded=false;
}else{println!("bad1");} }else{println!("bad1");}
}else{println!("bad2");} }else{println!("bad2");}
}else{println!("bad3");} }else{println!("bad3");}
@ -1149,7 +1162,7 @@ impl crate::instruction::InstructionConsumer<PhysicsInstruction> for PhysicsStat
None=>(), None=>(),
} }
self.body.velocity=v; self.body.velocity=v;
if self.grounded&&self.style.get_control(StyleModifiers::CONTROL_JUMP,self.controls){ if self.style.get_control(StyleModifiers::CONTROL_JUMP,self.controls){
self.jump(); self.jump();
} }
self.refresh_walk_target(); self.refresh_walk_target();
@ -1254,9 +1267,7 @@ impl crate::instruction::InstructionConsumer<PhysicsInstruction> for PhysicsStat
PhysicsInputInstruction::SetMoveDown(s) => self.set_control(StyleModifiers::CONTROL_MOVEDOWN,s), PhysicsInputInstruction::SetMoveDown(s) => self.set_control(StyleModifiers::CONTROL_MOVEDOWN,s),
PhysicsInputInstruction::SetJump(s) => { PhysicsInputInstruction::SetJump(s) => {
self.set_control(StyleModifiers::CONTROL_JUMP,s); self.set_control(StyleModifiers::CONTROL_JUMP,s);
if self.grounded{ self.jump();
self.jump();
}
refresh_walk_target_velocity=false; refresh_walk_target_velocity=false;
}, },
PhysicsInputInstruction::SetZoom(s) => { PhysicsInputInstruction::SetZoom(s) => {
@ -1270,8 +1281,7 @@ impl crate::instruction::InstructionConsumer<PhysicsInstruction> for PhysicsStat
//manual clear //for c in self.contacts{process_instruction(CollisionEnd(c))} //manual clear //for c in self.contacts{process_instruction(CollisionEnd(c))}
self.contacts.clear(); self.contacts.clear();
self.body.acceleration=self.style.gravity; self.body.acceleration=self.style.gravity;
self.walk.state=WalkEnum::Reached; self.move_state=MoveState::Air;
self.grounded=false;
refresh_walk_target=false; refresh_walk_target=false;
}, },
PhysicsInputInstruction::Idle => {refresh_walk_target=false;},//literally idle! PhysicsInputInstruction::Idle => {refresh_walk_target=false;},//literally idle!
@ -1279,9 +1289,20 @@ impl crate::instruction::InstructionConsumer<PhysicsInstruction> for PhysicsStat
if refresh_walk_target{ if refresh_walk_target{
//calculate walk target velocity //calculate walk target velocity
if refresh_walk_target_velocity{ if refresh_walk_target_velocity{
let camera_mat=self.camera.simulate_move_rotation_y(self.camera.mouse.lerp(&self.next_mouse,self.time).x); match self.move_state{
let control_dir=camera_mat*self.style.get_control_dir(self.controls); MoveState::Walk(walk_state)=>{
self.walk.target_velocity=control_dir*self.style.walkspeed; let camera_mat=self.camera.simulate_move_rotation_y(self.camera.mouse.lerp(&self.next_mouse,self.time).x);
let control_dir=camera_mat*self.style.get_control_dir(self.controls);
walk_state.target_velocity=control_dir*self.style.walkspeed;
},
MoveState::Ladder(walk_state)=>{
let camera_mat=self.camera.simulate_move_rotation_y(self.camera.mouse.lerp(&self.next_mouse,self.time).x);
let control_dir=camera_mat*self.style.get_control_dir(self.controls);
walk_state.target_velocity=control_dir*self.style.walkspeed;
},
MoveState::Water=>(),
MoveState::Air=>(),
}
} }
self.refresh_walk_target(); self.refresh_walk_target();
} }