forked from StrafesNET/strafe-client
overhaul WalkState + implement ladders
This commit is contained in:
parent
35bfd1d366
commit
d04d1be27e
@ -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){
|
||||||
|
10
src/model.rs
10
src/model.rs
@ -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{
|
||||||
|
167
src/physics.rs
167
src/physics.rs
@ -109,22 +109,54 @@ impl MouseState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum WalkEnum{
|
enum WalkEnum{
|
||||||
Reached,
|
Reached,
|
||||||
Transient,
|
Transient(WalkTarget),
|
||||||
|
}
|
||||||
|
struct WalkTarget{
|
||||||
|
velocity:Planar64Vec3,
|
||||||
|
time:Time,
|
||||||
|
}
|
||||||
|
struct WalkState{
|
||||||
|
normal:Planar64Vec3,
|
||||||
|
state:WalkEnum,
|
||||||
|
}
|
||||||
|
impl WalkEnum{
|
||||||
|
//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)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
pub struct WalkState {
|
|
||||||
pub target_velocity: Planar64Vec3,
|
|
||||||
pub target_time: Time,
|
|
||||||
pub state: WalkEnum,
|
|
||||||
}
|
}
|
||||||
impl WalkState{
|
impl WalkState{
|
||||||
pub fn new() -> Self {
|
fn ground(touching:&TouchingState,body:&Body,style:&StyleModifiers,models:&Vec<ModelPhysics>,mut velocity:Planar64Vec3)->(Self,Planar64Vec3){
|
||||||
Self{
|
let (walk_enum,a)=WalkEnum::with_target_velocity(touching,body,style,models,velocity,&Planar64Vec3::Y);
|
||||||
target_velocity:Planar64Vec3::ZERO,
|
(Self{
|
||||||
target_time:Time::ZERO,
|
state:walk_enum,
|
||||||
state:WalkEnum::Reached,
|
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();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
Loading…
Reference in New Issue
Block a user