overhaul WalkState + implement ladders

This commit is contained in:
Quaternions 2023-10-17 00:17:54 -07:00
parent 35bfd1d366
commit d04d1be27e
3 changed files with 108 additions and 89 deletions

View File

@ -97,8 +97,8 @@ fn get_attributes(name:&str,can_collide:bool,velocity:Planar64Vec3,force_interse
true=>{ true=>{
match name{ match name{
"Bounce"=>contacting.elasticity=Some(u32::MAX), "Bounce"=>contacting.elasticity=Some(u32::MAX),
"Surf"=>contacting.surf=Some(crate::model::ContactingSurf{}), "Surf"=>contacting.contact_behaviour=Some(crate::model::ContactingBehaviour::Surf),
"Ladder"=>contacting.ladder=Some(crate::model::ContactingLadder{sticky:true}), "Ladder"=>contacting.contact_behaviour=Some(crate::model::ContactingBehaviour::Ladder(crate::model::ContactingLadder{sticky:true})),
other=>{ other=>{
if let Some(captures)=lazy_regex::regex!(r"^(Jump|WormholeIn)(\d+)$") if let Some(captures)=lazy_regex::regex!(r"^(Jump|WormholeIn)(\d+)$")
.captures(other){ .captures(other){

View File

@ -92,11 +92,14 @@ pub enum TempIndexedAttributes{
//you have this effect while in contact //you have this effect while in contact
#[derive(Clone)] #[derive(Clone)]
pub struct ContactingSurf{}
#[derive(Clone)]
pub struct ContactingLadder{ pub struct ContactingLadder{
pub sticky:bool pub sticky:bool
} }
#[derive(Clone)]
pub enum ContactingBehaviour{
Surf,
Ladder(ContactingLadder),
}
//you have this effect while intersecting //you have this effect while intersecting
#[derive(Clone)] #[derive(Clone)]
pub struct IntersectingWater{ pub struct IntersectingWater{
@ -175,8 +178,7 @@ pub struct GameMechanicAttributes{
pub struct ContactingAttributes{ pub struct ContactingAttributes{
pub elasticity:Option<u32>,//[1/2^32,1] 0=None (elasticity+1)/2^32 pub elasticity:Option<u32>,//[1/2^32,1] 0=None (elasticity+1)/2^32
//friction? //friction?
pub surf:Option<ContactingSurf>, pub contact_behaviour:Option<ContactingBehaviour>,
pub ladder:Option<ContactingLadder>,
} }
#[derive(Default,Clone)] #[derive(Default,Clone)]
pub struct IntersectingAttributes{ pub struct IntersectingAttributes{

View File

@ -109,24 +109,56 @@ impl MouseState {
} }
} }
pub enum WalkEnum{ enum WalkEnum{
Reached, Reached,
Transient, Transient(WalkTarget),
} }
pub struct WalkState { struct WalkTarget{
pub target_velocity: Planar64Vec3, velocity:Planar64Vec3,
pub target_time: Time, time:Time,
pub state: WalkEnum,
} }
impl WalkState { struct WalkState{
pub fn new() -> Self { normal:Planar64Vec3,
Self{ state:WalkEnum,
target_velocity:Planar64Vec3::ZERO, }
target_time:Time::ZERO, impl WalkEnum{
state:WalkEnum::Reached, //args going crazy
//(walk_enum,body.acceleration)=with_target_velocity();
fn with_target_velocity(touching:&TouchingState,body:&Body,style:&StyleModifiers,models:&Vec<ModelPhysics>,mut velocity:Planar64Vec3,normal:&Planar64Vec3)->(WalkEnum,Planar64Vec3){
touching.constrain_velocity(models,&mut velocity);
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{
let mut a=Planar64Vec3::ZERO;
touching.constrain_acceleration(models,&mut a);
(WalkEnum::Reached,a)
}else{
//normal friction acceleration is clippedAcceleration.dot(normal)*friction
let accel=style.walk_accel.min(style.gravity.dot(Planar64Vec3::NEG_Y)*style.friction);
let time_delta=target_diff.length()/accel;
let mut a=target_diff.with_length(accel);
touching.constrain_acceleration(models,&mut a);
(WalkEnum::Transient(WalkTarget{velocity,time:body.time+Time::from(time_delta)}),a)
} }
} }
} }
impl WalkState{
fn ground(touching:&TouchingState,body:&Body,style:&StyleModifiers,models:&Vec<ModelPhysics>,mut velocity:Planar64Vec3)->(Self,Planar64Vec3){
let (walk_enum,a)=WalkEnum::with_target_velocity(touching,body,style,models,velocity,&Planar64Vec3::Y);
(Self{
state:walk_enum,
normal:Planar64Vec3::Y,
},a)
}
fn ladder(touching:&TouchingState,body:&Body,style:&StyleModifiers,models:&Vec<ModelPhysics>,mut velocity:Planar64Vec3,normal:&Planar64Vec3)->(Self,Planar64Vec3){
let (walk_enum,a)=WalkEnum::with_target_velocity(touching,body,style,models,velocity,normal);
(Self{
state:walk_enum,
normal:normal.clone(),
},a)
}
}
@ -280,8 +312,19 @@ impl StyleModifiers{
return control_dir return control_dir
} }
fn get_jump_power(&self)->Planar64Vec3{ fn get_jump_power(&self)->Planar64{
Planar64Vec3::int(0,715588,0)/(2*1000000/100) Planar64::int(715588)/(2*1000000/100)
}
fn get_walk_target_velocity(&self,camera:&PhysicsCamera,controls:u32,next_mouse:&MouseState,time:Time)->Planar64Vec3{
let camera_mat=camera.simulate_move_rotation_y(camera.mouse.lerp(&next_mouse,time).x);
let control_dir=camera_mat*self.get_control_dir(controls);
control_dir*self.walkspeed
}
fn get_propulsion_target_velocity(&self,camera:&PhysicsCamera,controls:u32,next_mouse:&MouseState,time:Time)->Planar64Vec3{
let camera_mat=camera.simulate_move_rotation(camera.mouse.lerp(&next_mouse,time));
let control_dir=camera_mat*self.get_control_dir(controls);
control_dir*self.walkspeed
} }
} }
@ -706,18 +749,12 @@ impl PhysicsState {
} }
fn jump(&mut self){ fn jump(&mut self){
match &self.move_state{ match &self.move_state{
MoveState::Air=>(), MoveState::Walk(walk_state)|MoveState::Ladder(walk_state)=>{
MoveState::Walk(walk_state)=>{ let mut v=self.body.velocity+walk_state.normal*self.style.get_jump_power();
let mut v=self.body.velocity+self.style.get_jump_power();
self.touching.constrain_velocity(&self.models,&mut v);
self.body.velocity=v;
},
MoveState::Water=>(),
MoveState::Ladder(walk_state)=>{
let mut v=self.body.velocity+self.style.get_jump_power();
self.touching.constrain_velocity(&self.models,&mut v); self.touching.constrain_velocity(&self.models,&mut v);
self.body.velocity=v; self.body.velocity=v;
}, },
MoveState::Air|MoveState::Water=>(),
} }
} }
@ -761,34 +798,15 @@ impl PhysicsState {
// } // }
fn refresh_walk_target(&mut self){ fn refresh_walk_target(&mut self){
//calculate acceleration yada yada
match &mut self.move_state{ match &mut self.move_state{
MoveState::Air=>(), MoveState::Air|MoveState::Water=>(),
MoveState::Walk(walk_state)=>{ MoveState::Walk(WalkState{normal,state})=>{
let mut v=walk_state.target_velocity; let n=normal;
self.touching.constrain_velocity(&self.models,&mut v); (*state,self.body.acceleration)=WalkEnum::with_target_velocity(&self.touching,&self.body,&self.style,&self.models,self.style.get_walk_target_velocity(&self.camera,self.controls,&self.next_mouse,self.time),&n);
let mut target_diff=v-self.body.velocity;
//remove normal component
target_diff-=Planar64Vec3::Y*target_diff.y();
if target_diff==Planar64Vec3::ZERO{
let mut a=Planar64Vec3::ZERO;
self.touching.constrain_acceleration(&self.models,&mut a);
self.body.acceleration=a;
walk_state.state=WalkEnum::Reached;
}else{
//normal friction acceleration is clippedAcceleration.dot(normal)*friction
let accel=self.style.walk_accel.min(self.style.gravity.dot(Planar64Vec3::NEG_Y)*self.style.friction);
let time_delta=target_diff.length()/accel;
let mut a=target_diff.with_length(accel);
self.touching.constrain_acceleration(&self.models,&mut a);
self.body.acceleration=a;
walk_state.target_time=self.body.time+Time::from(time_delta);
walk_state.state=WalkEnum::Transient;
}
}, },
MoveState::Water=>(), MoveState::Ladder(WalkState{normal,state})=>{
MoveState::Ladder(walk_state)=>{ let n=normal;
// (*state,self.body.acceleration)=WalkEnum::with_target_velocity(&self.touching,&self.body,&self.style,&self.models,self.style.get_propulsion_target_velocity(&self.camera,self.controls,&self.next_mouse,self.time),&n);
}, },
} }
} }
@ -796,8 +814,8 @@ impl PhysicsState {
//check if you have a valid walk state and create an instruction //check if you have a valid walk state and create an instruction
match &self.move_state{ match &self.move_state{
MoveState::Walk(walk_state)|MoveState::Ladder(walk_state)=>match &walk_state.state{ MoveState::Walk(walk_state)|MoveState::Ladder(walk_state)=>match &walk_state.state{
WalkEnum::Transient=>Some(TimedInstruction{ WalkEnum::Transient(walk_target)=>Some(TimedInstruction{
time:walk_state.target_time, time:walk_target.time,
instruction:PhysicsInstruction::ReachWalkTargetVelocity instruction:PhysicsInstruction::ReachWalkTargetVelocity
}), }),
WalkEnum::Reached=>None, WalkEnum::Reached=>None,
@ -1137,12 +1155,24 @@ impl crate::instruction::InstructionConsumer<PhysicsInstruction> for PhysicsStat
let model=c.model(&self.models).unwrap(); let model=c.model(&self.models).unwrap();
match &model.attributes{ match &model.attributes{
PhysicsCollisionAttributes::Contact{contacting,general}=>{ PhysicsCollisionAttributes::Contact{contacting,general}=>{
match &contacting.surf{ match &contacting.contact_behaviour{
Some(surf)=>println!("I'm surfing!"), Some(crate::model::ContactingBehaviour::Surf)=>println!("I'm surfing!"),
Some(crate::model::ContactingBehaviour::Ladder(contacting_ladder))=>{
if contacting_ladder.sticky{
//kill v
self.body.velocity=Planar64Vec3::ZERO;//model.velocity
}
//ladder walkstate
let (walk_state,a)=WalkState::ladder(&self.touching,&self.body,&self.style,&self.models,self.style.get_propulsion_target_velocity(&self.camera,self.controls,&self.next_mouse,self.time),&c.normal(&self.models));
self.move_state=MoveState::Ladder(walk_state);
self.body.acceleration=a;
}
None=>match &c.face { None=>match &c.face {
TreyMeshFace::Top => { TreyMeshFace::Top => {
//ground //ground
self.move_state=MoveState::Walk(WalkState::new()) let (walk_state,a)=WalkState::ground(&self.touching,&self.body,&self.style,&self.models,self.style.get_walk_target_velocity(&self.camera,self.controls,&self.next_mouse,self.time));
self.move_state=MoveState::Walk(walk_state);
self.body.acceleration=a;
}, },
_ => (), _ => (),
}, },
@ -1242,11 +1272,11 @@ impl crate::instruction::InstructionConsumer<PhysicsInstruction> for PhysicsStat
//check ground //check ground
match &c.face { match &c.face {
TreyMeshFace::Top => { TreyMeshFace::Top => {
//TODO: make this more advanced checking contacts
self.move_state=MoveState::Air; self.move_state=MoveState::Air;
}, },
_ => (), _=>self.refresh_walk_target(),
} }
self.refresh_walk_target();
}, },
PhysicsCollisionAttributes::Intersect{intersecting,general}=>{ PhysicsCollisionAttributes::Intersect{intersecting,general}=>{
self.touching.remove_intersect(c.model); self.touching.remove_intersect(c.model);
@ -1267,20 +1297,24 @@ impl crate::instruction::InstructionConsumer<PhysicsInstruction> for PhysicsStat
match &mut self.move_state{ match &mut self.move_state{
MoveState::Air|MoveState::Water=>(), MoveState::Air|MoveState::Water=>(),
MoveState::Walk(walk_state)|MoveState::Ladder(walk_state)=>{ MoveState::Walk(walk_state)|MoveState::Ladder(walk_state)=>{
match &mut walk_state.state{
WalkEnum::Reached=>(),
WalkEnum::Transient(walk_target)=>{
//precisely set velocity //precisely set velocity
let mut a=self.style.gravity; let mut a=self.style.gravity;
self.touching.constrain_acceleration(&self.models,&mut a); self.touching.constrain_acceleration(&self.models,&mut a);
self.body.acceleration=a; self.body.acceleration=a;
let mut v=walk_state.target_velocity; let mut v=walk_target.velocity;
self.touching.constrain_velocity(&self.models,&mut v); self.touching.constrain_velocity(&self.models,&mut v);
self.body.velocity=v; self.body.velocity=v;
walk_state.state=WalkEnum::Reached; walk_state.state=WalkEnum::Reached;
},
}
} }
} }
}, },
PhysicsInstruction::Input(input_instruction) => { PhysicsInstruction::Input(input_instruction) => {
let mut refresh_walk_target=true; let mut refresh_walk_target=true;
let mut refresh_walk_target_velocity=true;
match input_instruction{ match input_instruction{
PhysicsInputInstruction::SetNextMouse(m) => { PhysicsInputInstruction::SetNextMouse(m) => {
self.camera.move_mouse(self.next_mouse.pos); self.camera.move_mouse(self.next_mouse.pos);
@ -1299,7 +1333,7 @@ impl crate::instruction::InstructionConsumer<PhysicsInstruction> for PhysicsStat
PhysicsInputInstruction::SetJump(s) => { PhysicsInputInstruction::SetJump(s) => {
self.set_control(StyleModifiers::CONTROL_JUMP,s); self.set_control(StyleModifiers::CONTROL_JUMP,s);
self.jump(); self.jump();
refresh_walk_target_velocity=false; refresh_walk_target=false;
}, },
PhysicsInputInstruction::SetZoom(s) => { PhysicsInputInstruction::SetZoom(s) => {
self.set_control(StyleModifiers::CONTROL_ZOOM,s); self.set_control(StyleModifiers::CONTROL_ZOOM,s);
@ -1318,23 +1352,6 @@ impl crate::instruction::InstructionConsumer<PhysicsInstruction> for PhysicsStat
PhysicsInputInstruction::Idle => {refresh_walk_target=false;},//literally idle! PhysicsInputInstruction::Idle => {refresh_walk_target=false;},//literally idle!
} }
if refresh_walk_target{ if refresh_walk_target{
//calculate walk target velocity
if refresh_walk_target_velocity{
match &mut self.move_state{
MoveState::Walk(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::Ladder(walk_state)=>{
// let camera_mat=self.camera.simulate_move_rotation(self.camera.mouse.lerp(&self.next_mouse,self.time));
// 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();
} }
}, },