forked from StrafesNET/strafe-client
refactor physics instruction processing
This is an important engine upgrade: idle events do not donate their timestamp to engine objects and pollute the timeline with unnecessary game ticks that can be represented as analytic continuations of previous game ticks. This means that all "render" tick updates can be dropped from bot timelines. In other words, progressing the physics simulation is invariant to differing subdivisions of an overall time advancement with no external input.
This commit is contained in:
parent
e04e754abb
commit
755adeaefd
166
src/physics.rs
166
src/physics.rs
@ -13,8 +13,10 @@ use strafesnet_common::instruction::{self,InstructionEmitter,InstructionConsumer
|
|||||||
use strafesnet_common::integer::{self,Time,Planar64,Planar64Vec3,Planar64Mat3,Angle32,Ratio64Vec2};
|
use strafesnet_common::integer::{self,Time,Planar64,Planar64Vec3,Planar64Mat3,Angle32,Ratio64Vec2};
|
||||||
use gameplay::ModeState;
|
use gameplay::ModeState;
|
||||||
|
|
||||||
|
//internal influence
|
||||||
|
//when the physics asks itself what happens next, this is how it's represented
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum PhysicsInstruction {
|
enum PhysicsInternalInstruction{
|
||||||
CollisionStart(Collision),
|
CollisionStart(Collision),
|
||||||
CollisionEnd(Collision),
|
CollisionEnd(Collision),
|
||||||
StrafeTick,
|
StrafeTick,
|
||||||
@ -25,10 +27,9 @@ pub enum PhysicsInstruction {
|
|||||||
// bool,//true = Trigger; false = teleport
|
// bool,//true = Trigger; false = teleport
|
||||||
// bool,//true = Force
|
// bool,//true = Force
|
||||||
// )
|
// )
|
||||||
//InputInstructions conditionally activate RefreshWalkTarget (by doing what SetWalkTargetVelocity used to do and then flagging it)
|
|
||||||
Input(PhysicsInputInstruction),
|
|
||||||
SetSensitivity(Ratio64Vec2),
|
|
||||||
}
|
}
|
||||||
|
//external influence
|
||||||
|
//this is how you influence the physics from outside
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum PhysicsInputInstruction{
|
pub enum PhysicsInputInstruction{
|
||||||
ReplaceMouse(MouseState,MouseState),
|
ReplaceMouse(MouseState,MouseState),
|
||||||
@ -47,6 +48,14 @@ pub enum PhysicsInputInstruction {
|
|||||||
//for interpolation / networking / playback reasons, most playback heads will always want
|
//for interpolation / networking / playback reasons, most playback heads will always want
|
||||||
//to be 1 instruction ahead to generate the next state for interpolation.
|
//to be 1 instruction ahead to generate the next state for interpolation.
|
||||||
PracticeFly,
|
PracticeFly,
|
||||||
|
SetSensitivity(Ratio64Vec2),
|
||||||
|
}
|
||||||
|
#[derive(Debug)]
|
||||||
|
enum PhysicsInstruction{
|
||||||
|
Internal(PhysicsInternalInstruction),
|
||||||
|
//InputInstructions conditionally activate RefreshWalkTarget
|
||||||
|
//(by doing what SetWalkTargetVelocity used to do and then flagging it)
|
||||||
|
Input(PhysicsInputInstruction),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone,Copy,Debug,Default,Hash)]
|
#[derive(Clone,Copy,Debug,Default,Hash)]
|
||||||
@ -559,13 +568,13 @@ impl MoveState{
|
|||||||
=>None,
|
=>None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn next_move_instruction(&self,strafe:&Option<gameplay_style::StrafeSettings>,time:Time)->Option<TimedInstruction<PhysicsInstruction>>{
|
fn next_move_instruction(&self,strafe:&Option<gameplay_style::StrafeSettings>,time:Time)->Option<TimedInstruction<PhysicsInternalInstruction>>{
|
||||||
//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{
|
match self{
|
||||||
MoveState::Walk(walk_state)|MoveState::Ladder(walk_state)=>match &walk_state.target{
|
MoveState::Walk(walk_state)|MoveState::Ladder(walk_state)=>match &walk_state.target{
|
||||||
&TransientAcceleration::Reachable{acceleration:_,time}=>Some(TimedInstruction{
|
&TransientAcceleration::Reachable{acceleration:_,time}=>Some(TimedInstruction{
|
||||||
time,
|
time,
|
||||||
instruction:PhysicsInstruction::ReachWalkTargetVelocity
|
instruction:PhysicsInternalInstruction::ReachWalkTargetVelocity
|
||||||
}),
|
}),
|
||||||
TransientAcceleration::Unreachable{acceleration:_}
|
TransientAcceleration::Unreachable{acceleration:_}
|
||||||
|TransientAcceleration::Reached
|
|TransientAcceleration::Reached
|
||||||
@ -575,7 +584,7 @@ impl MoveState{
|
|||||||
TimedInstruction{
|
TimedInstruction{
|
||||||
time:strafe.next_tick(time),
|
time:strafe.next_tick(time),
|
||||||
//only poll the physics if there is a before and after mouse event
|
//only poll the physics if there is a before and after mouse event
|
||||||
instruction:PhysicsInstruction::StrafeTick
|
instruction:PhysicsInternalInstruction::StrafeTick
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
MoveState::Water=>None,//TODO
|
MoveState::Water=>None,//TODO
|
||||||
@ -769,7 +778,7 @@ impl TouchingState{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn predict_collision_end(&self,collector:&mut instruction::InstructionCollector<PhysicsInstruction>,models:&PhysicsModels,hitbox_mesh:&HitboxMesh,body:&Body,time:Time){
|
fn predict_collision_end(&self,collector:&mut instruction::InstructionCollector<PhysicsInternalInstruction>,models:&PhysicsModels,hitbox_mesh:&HitboxMesh,body:&Body,time:Time){
|
||||||
let relative_body=VirtualBody::relative(&Body::default(),body).body(time);
|
let relative_body=VirtualBody::relative(&Body::default(),body).body(time);
|
||||||
for contact in &self.contacts{
|
for contact in &self.contacts{
|
||||||
//detect face slide off
|
//detect face slide off
|
||||||
@ -778,7 +787,7 @@ impl TouchingState{
|
|||||||
collector.collect(minkowski.predict_collision_face_out(&relative_body,collector.time(),contact.face_id).map(|(_face,time)|{
|
collector.collect(minkowski.predict_collision_face_out(&relative_body,collector.time(),contact.face_id).map(|(_face,time)|{
|
||||||
TimedInstruction{
|
TimedInstruction{
|
||||||
time,
|
time,
|
||||||
instruction:PhysicsInstruction::CollisionEnd(
|
instruction:PhysicsInternalInstruction::CollisionEnd(
|
||||||
Collision::Contact(ContactCollision{convex_mesh_id:contact.convex_mesh_id,face_id:contact.face_id})
|
Collision::Contact(ContactCollision{convex_mesh_id:contact.convex_mesh_id,face_id:contact.face_id})
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
@ -791,7 +800,7 @@ impl TouchingState{
|
|||||||
collector.collect(minkowski.predict_collision_out(&relative_body,collector.time()).map(|(_face,time)|{
|
collector.collect(minkowski.predict_collision_out(&relative_body,collector.time()).map(|(_face,time)|{
|
||||||
TimedInstruction{
|
TimedInstruction{
|
||||||
time,
|
time,
|
||||||
instruction:PhysicsInstruction::CollisionEnd(
|
instruction:PhysicsInternalInstruction::CollisionEnd(
|
||||||
Collision::Intersect(IntersectCollision{convex_mesh_id:intersect.convex_mesh_id})
|
Collision::Intersect(IntersectCollision{convex_mesh_id:intersect.convex_mesh_id})
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
@ -954,11 +963,7 @@ impl PhysicsState {
|
|||||||
fn clear(&mut self){
|
fn clear(&mut self){
|
||||||
self.touching.clear();
|
self.touching.clear();
|
||||||
}
|
}
|
||||||
fn advance_time(&mut self, time: Time){
|
fn next_move_instruction(&self)->Option<TimedInstruction<PhysicsInternalInstruction>>{
|
||||||
self.body.advance_time(time);
|
|
||||||
self.time=time;
|
|
||||||
}
|
|
||||||
fn next_move_instruction(&self)->Option<TimedInstruction<PhysicsInstruction>>{
|
|
||||||
self.move_state.next_move_instruction(&self.style.strafe,self.time)
|
self.move_state.next_move_instruction(&self.style.strafe,self.time)
|
||||||
}
|
}
|
||||||
//lmao idk this is convenient
|
//lmao idk this is convenient
|
||||||
@ -1031,31 +1036,33 @@ pub struct PhysicsContext{
|
|||||||
state:PhysicsState,//this captures the entire state of the physics.
|
state:PhysicsState,//this captures the entire state of the physics.
|
||||||
data:PhysicsData,//data currently loaded into memory which is needded for physics to run, but is not part of the state.
|
data:PhysicsData,//data currently loaded into memory which is needded for physics to run, but is not part of the state.
|
||||||
}
|
}
|
||||||
|
//the physics consumes the generic PhysicsInstruction, but can only emit the more narrow PhysicsInternalInstruction
|
||||||
impl instruction::InstructionConsumer<PhysicsInstruction> for PhysicsContext{
|
impl instruction::InstructionConsumer<PhysicsInstruction> for PhysicsContext{
|
||||||
fn process_instruction(&mut self,ins:TimedInstruction<PhysicsInstruction>){
|
fn process_instruction(&mut self,ins:TimedInstruction<PhysicsInstruction>){
|
||||||
atomic_state_update(&mut self.state,&self.data,ins)
|
atomic_state_update(&mut self.state,&self.data,ins)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl instruction::InstructionEmitter<PhysicsInstruction> for PhysicsContext{
|
impl instruction::InstructionEmitter<PhysicsInternalInstruction> for PhysicsContext{
|
||||||
//this little next instruction function can cache its return value and invalidate the cached value by watching the State.
|
//this little next instruction function can cache its return value and invalidate the cached value by watching the State.
|
||||||
fn next_instruction(&self,time_limit:Time)->Option<TimedInstruction<PhysicsInstruction>>{
|
fn next_instruction(&self,time_limit:Time)->Option<TimedInstruction<PhysicsInternalInstruction>>{
|
||||||
literally_next_instruction_but_with_context(&self.state,&self.data,time_limit)
|
next_instruction_internal(&self.state,&self.data,time_limit)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl PhysicsContext{
|
impl PhysicsContext{
|
||||||
pub fn clear(&mut self){
|
pub fn clear(&mut self){
|
||||||
self.state.clear();
|
self.state.clear();
|
||||||
}
|
}
|
||||||
|
//TODO: remove non-standard interfaces to process_instruction
|
||||||
pub fn load_user_settings(&mut self,user_settings:&crate::settings::UserSettings){
|
pub fn load_user_settings(&mut self,user_settings:&crate::settings::UserSettings){
|
||||||
self.process_instruction(TimedInstruction{
|
self.run_input_instruction(TimedInstruction{
|
||||||
time:self.state.time,
|
time:self.state.time,
|
||||||
instruction:PhysicsInstruction::SetSensitivity(user_settings.calculate_sensitivity()),
|
instruction:PhysicsInputInstruction::SetSensitivity(user_settings.calculate_sensitivity()),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
pub fn spawn(&mut self){
|
pub fn spawn(&mut self){
|
||||||
self.process_instruction(TimedInstruction{
|
self.run_input_instruction(TimedInstruction{
|
||||||
time:self.state.time,
|
time:self.state.time,
|
||||||
instruction:PhysicsInstruction::Input(PhysicsInputInstruction::Reset),
|
instruction:PhysicsInputInstruction::Reset,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
pub const fn output(&self)->PhysicsOutputState{
|
pub const fn output(&self)->PhysicsOutputState{
|
||||||
@ -1141,16 +1148,19 @@ impl PhysicsContext{
|
|||||||
}
|
}
|
||||||
|
|
||||||
//tickless gaming
|
//tickless gaming
|
||||||
fn run(&mut self,time_limit:Time){
|
fn run_internal_exhaustive(&mut self,time_limit:Time){
|
||||||
//prepare is ommitted - everything is done via instructions.
|
//prepare is ommitted - everything is done via instructions.
|
||||||
while let Some(instruction)=self.next_instruction(time_limit){//collect
|
while let Some(instruction)=self.next_instruction(time_limit){//collect
|
||||||
//process
|
//process
|
||||||
self.process_instruction(instruction);
|
self.process_instruction(TimedInstruction{
|
||||||
|
time:instruction.time,
|
||||||
|
instruction:PhysicsInstruction::Internal(instruction.instruction),
|
||||||
|
});
|
||||||
//write hash lol
|
//write hash lol
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn run_input_instruction(&mut self,instruction:TimedInstruction<PhysicsInputInstruction>){
|
pub fn run_input_instruction(&mut self,instruction:TimedInstruction<PhysicsInputInstruction>){
|
||||||
self.run(instruction.time);
|
self.run_internal_exhaustive(instruction.time);
|
||||||
self.process_instruction(TimedInstruction{
|
self.process_instruction(TimedInstruction{
|
||||||
time:instruction.time,
|
time:instruction.time,
|
||||||
instruction:PhysicsInstruction::Input(instruction.instruction),
|
instruction:PhysicsInstruction::Input(instruction.instruction),
|
||||||
@ -1158,7 +1168,8 @@ impl PhysicsContext{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn literally_next_instruction_but_with_context(state:&PhysicsState,data:&PhysicsData,time_limit:Time)->Option<TimedInstruction<PhysicsInstruction>>{
|
//this is the one who asks
|
||||||
|
fn next_instruction_internal(state:&PhysicsState,data:&PhysicsData,time_limit:Time)->Option<TimedInstruction<PhysicsInternalInstruction>>{
|
||||||
//JUST POLLING!!! NO MUTATION
|
//JUST POLLING!!! NO MUTATION
|
||||||
let mut collector = instruction::InstructionCollector::new(time_limit);
|
let mut collector = instruction::InstructionCollector::new(time_limit);
|
||||||
|
|
||||||
@ -1180,7 +1191,7 @@ impl PhysicsContext{
|
|||||||
//temp (?) code to avoid collision loops
|
//temp (?) code to avoid collision loops
|
||||||
.map_or(None,|(face,time)|if time==state.time{None}else{Some((face,time))})
|
.map_or(None,|(face,time)|if time==state.time{None}else{Some((face,time))})
|
||||||
.map(|(face,time)|{
|
.map(|(face,time)|{
|
||||||
TimedInstruction{time,instruction:PhysicsInstruction::CollisionStart(match data.models.attr(convex_mesh_id.model_id){
|
TimedInstruction{time,instruction:PhysicsInternalInstruction::CollisionStart(match data.models.attr(convex_mesh_id.model_id){
|
||||||
PhysicsCollisionAttributes::Contact{contacting:_,general:_}=>Collision::Contact(ContactCollision{convex_mesh_id,face_id:face}),
|
PhysicsCollisionAttributes::Contact{contacting:_,general:_}=>Collision::Contact(ContactCollision{convex_mesh_id,face_id:face}),
|
||||||
PhysicsCollisionAttributes::Intersect{intersecting:_,general:_}=>Collision::Intersect(IntersectCollision{convex_mesh_id}),
|
PhysicsCollisionAttributes::Intersect{intersecting:_,general:_}=>Collision::Intersect(IntersectCollision{convex_mesh_id}),
|
||||||
})}
|
})}
|
||||||
@ -1316,27 +1327,18 @@ fn run_teleport_behaviour(wormhole:&Option<gameplay_attributes::Wormhole>,models
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn atomic_state_update(state:&mut PhysicsState,data:&PhysicsData,ins:TimedInstruction<PhysicsInstruction>){
|
fn atomic_internal_instruction(state:&mut PhysicsState,data:&PhysicsData,ins:TimedInstruction<PhysicsInternalInstruction>){
|
||||||
match &ins.instruction{
|
let should_advance_body=match ins.instruction{
|
||||||
PhysicsInstruction::Input(PhysicsInputInstruction::Idle)
|
PhysicsInternalInstruction::CollisionStart(_)
|
||||||
|PhysicsInstruction::Input(PhysicsInputInstruction::SetNextMouse(_))
|
|PhysicsInternalInstruction::CollisionEnd(_)
|
||||||
|PhysicsInstruction::Input(PhysicsInputInstruction::ReplaceMouse(_,_))
|
|PhysicsInternalInstruction::StrafeTick
|
||||||
|PhysicsInstruction::StrafeTick=>(),
|
|PhysicsInternalInstruction::ReachWalkTargetVelocity=>true,
|
||||||
_=>println!("{}|{:?}",ins.time,ins.instruction),
|
};
|
||||||
}
|
if should_advance_body{
|
||||||
//selectively update body
|
state.body.advance_time(state.time);
|
||||||
match &ins.instruction{
|
|
||||||
PhysicsInstruction::Input(PhysicsInputInstruction::Idle)=>state.time=ins.time,//idle simply updates time
|
|
||||||
PhysicsInstruction::Input(_)
|
|
||||||
|PhysicsInstruction::ReachWalkTargetVelocity
|
|
||||||
|PhysicsInstruction::CollisionStart(_)
|
|
||||||
|PhysicsInstruction::CollisionEnd(_)
|
|
||||||
|PhysicsInstruction::StrafeTick
|
|
||||||
|PhysicsInstruction::SetSensitivity(_)
|
|
||||||
=>state.advance_time(ins.time),
|
|
||||||
}
|
}
|
||||||
match ins.instruction{
|
match ins.instruction{
|
||||||
PhysicsInstruction::CollisionStart(collision)=>{
|
PhysicsInternalInstruction::CollisionStart(collision)=>{
|
||||||
let convex_mesh_id=collision.convex_mesh_id();
|
let convex_mesh_id=collision.convex_mesh_id();
|
||||||
match (data.models.attr(convex_mesh_id.model_id),&collision){
|
match (data.models.attr(convex_mesh_id.model_id),&collision){
|
||||||
(PhysicsCollisionAttributes::Contact{contacting,general},&Collision::Contact(contact))=>{
|
(PhysicsCollisionAttributes::Contact{contacting,general},&Collision::Contact(contact))=>{
|
||||||
@ -1445,7 +1447,7 @@ fn run_teleport_behaviour(wormhole:&Option<gameplay_attributes::Wormhole>,models
|
|||||||
_=>panic!("invalid pair"),
|
_=>panic!("invalid pair"),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
PhysicsInstruction::CollisionEnd(collision)=>{
|
PhysicsInternalInstruction::CollisionEnd(collision)=>{
|
||||||
match (data.models.attr(collision.convex_mesh_id().model_id),&collision){
|
match (data.models.attr(collision.convex_mesh_id().model_id),&collision){
|
||||||
(PhysicsCollisionAttributes::Contact{contacting:_,general:_},&Collision::Contact(contact))=>{
|
(PhysicsCollisionAttributes::Contact{contacting:_,general:_},&Collision::Contact(contact))=>{
|
||||||
state.touching.remove(&collision);//remove contact before calling contact_constrain_acceleration
|
state.touching.remove(&collision);//remove contact before calling contact_constrain_acceleration
|
||||||
@ -1478,7 +1480,7 @@ fn run_teleport_behaviour(wormhole:&Option<gameplay_attributes::Wormhole>,models
|
|||||||
_=>panic!("invalid pair"),
|
_=>panic!("invalid pair"),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
PhysicsInstruction::StrafeTick=>{
|
PhysicsInternalInstruction::StrafeTick=>{
|
||||||
//TODO make this less huge
|
//TODO make this less huge
|
||||||
if let Some(strafe_settings)=&state.style.strafe{
|
if let Some(strafe_settings)=&state.style.strafe{
|
||||||
let controls=state.input_state.controls;
|
let controls=state.input_state.controls;
|
||||||
@ -1496,7 +1498,7 @@ fn run_teleport_behaviour(wormhole:&Option<gameplay_attributes::Wormhole>,models
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
PhysicsInstruction::ReachWalkTargetVelocity=>{
|
PhysicsInternalInstruction::ReachWalkTargetVelocity=>{
|
||||||
match &mut state.move_state{
|
match &mut state.move_state{
|
||||||
MoveState::Air
|
MoveState::Air
|
||||||
|MoveState::Water
|
|MoveState::Water
|
||||||
@ -1520,10 +1522,48 @@ fn run_teleport_behaviour(wormhole:&Option<gameplay_attributes::Wormhole>,models
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
PhysicsInstruction::SetSensitivity(sensitivity)=>state.camera.sensitivity=sensitivity,
|
}
|
||||||
PhysicsInstruction::Input(input_instruction)=>{
|
}
|
||||||
|
|
||||||
|
fn atomic_input_instruction(state:&mut PhysicsState,data:&PhysicsData,ins:TimedInstruction<PhysicsInputInstruction>){
|
||||||
|
let should_advance_body=match ins.instruction{
|
||||||
|
//the body may as well be a quantum wave function
|
||||||
|
//as far as these instruction are concerned (they don't care where it is)
|
||||||
|
PhysicsInputInstruction::SetSensitivity(..)
|
||||||
|
|PhysicsInputInstruction::Reset
|
||||||
|
|PhysicsInputInstruction::SetZoom(..)
|
||||||
|
|PhysicsInputInstruction::Idle=>false,
|
||||||
|
//these controls only update the body if you are on the ground
|
||||||
|
PhysicsInputInstruction::SetNextMouse(..)
|
||||||
|
|PhysicsInputInstruction::ReplaceMouse(..)
|
||||||
|
|PhysicsInputInstruction::SetMoveForward(..)
|
||||||
|
|PhysicsInputInstruction::SetMoveLeft(..)
|
||||||
|
|PhysicsInputInstruction::SetMoveBack(..)
|
||||||
|
|PhysicsInputInstruction::SetMoveRight(..)
|
||||||
|
|PhysicsInputInstruction::SetMoveUp(..)
|
||||||
|
|PhysicsInputInstruction::SetMoveDown(..)
|
||||||
|
|PhysicsInputInstruction::SetJump(..)=>{
|
||||||
|
//technically this could be refined further
|
||||||
|
//and only advance if you are moving relative to the contact
|
||||||
|
//but this is good enough for now
|
||||||
|
match &state.move_state{
|
||||||
|
MoveState::Fly
|
||||||
|
|MoveState::Water
|
||||||
|
|MoveState::Walk(_)
|
||||||
|
|MoveState::Ladder(_)=>true,
|
||||||
|
MoveState::Air=>false,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
//the body must be updated unconditionally
|
||||||
|
PhysicsInputInstruction::PracticeFly=>true,
|
||||||
|
};
|
||||||
|
if should_advance_body{
|
||||||
|
state.body.advance_time(state.time);
|
||||||
|
}
|
||||||
|
//TODO: UNTAB
|
||||||
let mut b_refresh_walk_target=true;
|
let mut b_refresh_walk_target=true;
|
||||||
match input_instruction{
|
match ins.instruction{
|
||||||
|
PhysicsInputInstruction::SetSensitivity(sensitivity)=>state.camera.sensitivity=sensitivity,
|
||||||
PhysicsInputInstruction::SetNextMouse(m)=>{
|
PhysicsInputInstruction::SetNextMouse(m)=>{
|
||||||
state.camera.move_mouse(state.input_state.mouse_delta());
|
state.camera.move_mouse(state.input_state.mouse_delta());
|
||||||
state.input_state.set_next_mouse(m);
|
state.input_state.set_next_mouse(m);
|
||||||
@ -1539,7 +1579,6 @@ fn run_teleport_behaviour(wormhole:&Option<gameplay_attributes::Wormhole>,models
|
|||||||
PhysicsInputInstruction::SetMoveUp(s)=>state.input_state.set_control(Controls::MoveUp,s),
|
PhysicsInputInstruction::SetMoveUp(s)=>state.input_state.set_control(Controls::MoveUp,s),
|
||||||
PhysicsInputInstruction::SetMoveDown(s)=>state.input_state.set_control(Controls::MoveDown,s),
|
PhysicsInputInstruction::SetMoveDown(s)=>state.input_state.set_control(Controls::MoveDown,s),
|
||||||
PhysicsInputInstruction::SetJump(s)=>{
|
PhysicsInputInstruction::SetJump(s)=>{
|
||||||
b_refresh_walk_target=false;
|
|
||||||
state.input_state.set_control(Controls::Jump,s);
|
state.input_state.set_control(Controls::Jump,s);
|
||||||
if let Some(walk_state)=state.move_state.get_walk_state(){
|
if let Some(walk_state)=state.move_state.get_walk_state(){
|
||||||
if let Some(jump_settings)=&state.style.jump{
|
if let Some(jump_settings)=&state.style.jump{
|
||||||
@ -1548,6 +1587,7 @@ fn run_teleport_behaviour(wormhole:&Option<gameplay_attributes::Wormhole>,models
|
|||||||
state.cull_velocity(&data,jumped_velocity);
|
state.cull_velocity(&data,jumped_velocity);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
b_refresh_walk_target=false;
|
||||||
},
|
},
|
||||||
PhysicsInputInstruction::SetZoom(s)=>{
|
PhysicsInputInstruction::SetZoom(s)=>{
|
||||||
state.input_state.set_control(Controls::Zoom,s);
|
state.input_state.set_control(Controls::Zoom,s);
|
||||||
@ -1577,13 +1617,29 @@ fn run_teleport_behaviour(wormhole:&Option<gameplay_attributes::Wormhole>,models
|
|||||||
}
|
}
|
||||||
b_refresh_walk_target=false;
|
b_refresh_walk_target=false;
|
||||||
},
|
},
|
||||||
PhysicsInputInstruction::Idle=>{b_refresh_walk_target=false;},//literally idle!
|
PhysicsInputInstruction::Idle=>{
|
||||||
|
//literally idle!
|
||||||
|
b_refresh_walk_target=false;
|
||||||
|
},
|
||||||
}
|
}
|
||||||
if b_refresh_walk_target{
|
if b_refresh_walk_target{
|
||||||
state.apply_input_and_body(data);
|
state.apply_input_and_body(data);
|
||||||
state.cull_velocity(data,state.body.velocity);
|
state.cull_velocity(data,state.body.velocity);
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
|
|
||||||
|
fn atomic_state_update(state:&mut PhysicsState,data:&PhysicsData,ins:TimedInstruction<PhysicsInstruction>){
|
||||||
|
match &ins.instruction{
|
||||||
|
PhysicsInstruction::Input(PhysicsInputInstruction::Idle)
|
||||||
|
|PhysicsInstruction::Input(PhysicsInputInstruction::SetNextMouse(_))
|
||||||
|
|PhysicsInstruction::Input(PhysicsInputInstruction::ReplaceMouse(_,_))
|
||||||
|
|PhysicsInstruction::Internal(PhysicsInternalInstruction::StrafeTick)=>(),
|
||||||
|
_=>println!("{}|{:?}",ins.time,ins.instruction),
|
||||||
|
}
|
||||||
|
state.time=ins.time;
|
||||||
|
match ins.instruction{
|
||||||
|
PhysicsInstruction::Internal(instruction)=>atomic_internal_instruction(state,data,TimedInstruction{time:ins.time,instruction}),
|
||||||
|
PhysicsInstruction::Input(instruction)=>atomic_input_instruction(state,data,TimedInstruction{time:ins.time,instruction}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -190,7 +190,7 @@ mod test{
|
|||||||
for _ in 0..5 {
|
for _ in 0..5 {
|
||||||
let task = instruction::TimedInstruction{
|
let task = instruction::TimedInstruction{
|
||||||
time:integer::Time::ZERO,
|
time:integer::Time::ZERO,
|
||||||
instruction:physics::PhysicsInstruction::StrafeTick,
|
instruction:physics::PhysicsInputInstruction::Idle,
|
||||||
};
|
};
|
||||||
worker.send(task).unwrap();
|
worker.send(task).unwrap();
|
||||||
}
|
}
|
||||||
@ -204,7 +204,7 @@ mod test{
|
|||||||
// Send a new task
|
// Send a new task
|
||||||
let task = instruction::TimedInstruction{
|
let task = instruction::TimedInstruction{
|
||||||
time:integer::Time::ZERO,
|
time:integer::Time::ZERO,
|
||||||
instruction:physics::PhysicsInstruction::StrafeTick,
|
instruction:physics::PhysicsInputInstruction::Idle,
|
||||||
};
|
};
|
||||||
worker.send(task).unwrap();
|
worker.send(task).unwrap();
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user