update mouse interpolator code

This commit is contained in:
Quaternions 2025-01-08 00:57:57 -08:00
parent 2e88ae0612
commit 3f0e3e0d3c
2 changed files with 42 additions and 37 deletions

View File

@ -1,9 +1,9 @@
use strafesnet_common::instruction;
use strafesnet_common::mouse::MouseState; use strafesnet_common::mouse::MouseState;
use strafesnet_common::physics::Instruction as PhysicsInputInstruction; use strafesnet_common::physics::{Instruction as PhysicsInputInstruction,Time as PhysicsTime,TimeInner as PhysicsTimeInner};
use strafesnet_common::integer::Time; use strafesnet_common::session::{Time as SessionTime,TimeInner as SessionTimeInner};
use strafesnet_common::instruction::TimedInstruction; use strafesnet_common::instruction::TimedInstruction;
use strafesnet_common::timer::{Scaled,Timer,TimerState}; use strafesnet_common::timer::{Scaled,Timer,TimerState};
#[derive(Debug)] #[derive(Debug)]
pub enum InputInstruction{ pub enum InputInstruction{
MoveMouse(glam::IVec2), MoveMouse(glam::IVec2),
@ -28,35 +28,24 @@ pub enum Instruction{
SetPaused(bool), SetPaused(bool),
//Graphics(crate::graphics_worker::Instruction), //Graphics(crate::graphics_worker::Instruction),
} }
pub struct MouseInterpolator{
//"MouseInterpolator"
timeline:std::collections::VecDeque<TimedInstruction<PhysicsInputInstruction>>,
last_mouse_time:Time,//this value is pre-transformed to simulation time
mouse_blocking:bool,
//"Simulation"
timer:Timer<Scaled>,
}
impl instruction::InstructionConsumer<Instruction> for MouseInterpolator{
fn process_instruction(&mut self,ins:TimedInstruction<Instruction>){
self.atomic_state_update(ins)
}
}
impl instruction::InstructionEmitter<PhysicsInputInstruction> for MouseInterpolator{
fn next_instruction(&self,time_limit:Time)->Option<TimedInstruction<PhysicsInputInstruction>>{
self.next_instruction_internal(time_limit)
}
}
pub struct MouseInterpolator{
timeline:std::collections::VecDeque<TimedInstruction<PhysicsInputInstruction,PhysicsTimeInner>>,
last_mouse_time:PhysicsTime,
mouse_blocking:bool,
}
impl MouseInterpolator{ impl MouseInterpolator{
pub fn new( )->Self{ pub fn new(
Self{ physics:crate::physics::PhysicsContext,
user_settings:crate::settings::UserSettings,
)->MouseInterpolator{
MouseInterpolator{
mouse_blocking:true, mouse_blocking:true,
last_mouse_time:physics.get_next_mouse().time, last_mouse_time:physics.get_next_mouse().time,
timeline:std::collections::VecDeque::new(), timeline:std::collections::VecDeque::new(),
timer:Timer::from_state(Scaled::identity(),false),
} }
} }
fn push_mouse_instruction(&mut self,ins:&TimedInstruction<Instruction>,m:glam::IVec2){ fn push_mouse_instruction(&mut self,ins:&TimedInstruction<Instruction,SessionTimeInner>,m:glam::IVec2){
if self.mouse_blocking{ if self.mouse_blocking{
//tell the game state which is living in the past about its future //tell the game state which is living in the past about its future
self.timeline.push_front(TimedInstruction{ self.timeline.push_front(TimedInstruction{
@ -78,7 +67,7 @@ impl MouseInterpolator{
} }
self.last_mouse_time=self.timer.time(ins.time); self.last_mouse_time=self.timer.time(ins.time);
} }
fn push(&mut self,time:Time,phys_input:PhysicsInputInstruction){ fn push(&mut self,time:SessionTime,phys_input:PhysicsInputInstruction){
//This is always a non-mouse event //This is always a non-mouse event
self.timeline.push_back(TimedInstruction{ self.timeline.push_back(TimedInstruction{
time:self.timer.time(time), time:self.timer.time(time),
@ -87,7 +76,7 @@ impl MouseInterpolator{
} }
/// returns should_empty_queue /// returns should_empty_queue
/// may or may not mutate internal state XD! /// may or may not mutate internal state XD!
fn map_instruction(&mut self,ins:&TimedInstruction<Instruction>)->bool{ fn map_instruction(&mut self,ins:&TimedInstruction<Instruction,SessionTimeInner>)->bool{
let mut update_mouse_blocking=true; let mut update_mouse_blocking=true;
match &ins.instruction{ match &ins.instruction{
Instruction::Input(input_instruction)=>match input_instruction{ Instruction::Input(input_instruction)=>match input_instruction{
@ -138,7 +127,7 @@ impl MouseInterpolator{
} }
} }
/// must check if self.mouse_blocking==true before calling! /// must check if self.mouse_blocking==true before calling!
fn unblock_mouse(&mut self,time:Time){ fn unblock_mouse(&mut self,time:SessionTime){
//push an event to extrapolate no movement from //push an event to extrapolate no movement from
self.timeline.push_front(TimedInstruction{ self.timeline.push_front(TimedInstruction{
time:self.last_mouse_time, time:self.last_mouse_time,
@ -148,13 +137,13 @@ impl MouseInterpolator{
//stop blocking. the mouse is not moving so the physics does not need to live in the past and wait for interpolation targets. //stop blocking. the mouse is not moving so the physics does not need to live in the past and wait for interpolation targets.
self.mouse_blocking=false; self.mouse_blocking=false;
} }
fn update_mouse_blocking(&mut self,time:Time)->bool{ fn update_mouse_blocking(&mut self,time:SessionTime)->bool{
if self.mouse_blocking{ if self.mouse_blocking{
//assume the mouse has stopped moving after 10ms. //assume the mouse has stopped moving after 10ms.
//shitty mice are 125Hz which is 8ms so this should cover that. //shitty mice are 125Hz which is 8ms so this should cover that.
//setting this to 100us still doesn't print even though it's 10x lower than the polling rate, //setting this to 100us still doesn't print even though it's 10x lower than the polling rate,
//so mouse events are probably not handled separately from drawing and fire right before it :( //so mouse events are probably not handled separately from drawing and fire right before it :(
if Time::from_millis(10)<self.timer.time(time)-self.physics.get_next_mouse().time{ if PhysicsTime::from_millis(10)<self.timer.time(time)-self.physics.get_next_mouse().time{
self.unblock_mouse(time); self.unblock_mouse(time);
true true
}else{ }else{
@ -172,20 +161,20 @@ impl MouseInterpolator{
self.physics.run_input_instruction(instruction); self.physics.run_input_instruction(instruction);
} }
} }
pub fn handle_instruction(&mut self,ins:&TimedInstruction<Instruction>){ pub fn handle_instruction(&mut self,ins:&TimedInstruction<Instruction,SessionTimeInner>){
let should_empty_queue=self.map_instruction(ins); let should_empty_queue=self.map_instruction(ins);
if should_empty_queue{ if should_empty_queue{
self.empty_queue(); self.empty_queue();
} }
} }
pub fn get_frame_state(&self,time:Time)->crate::graphics::FrameState{ pub fn get_frame_state(&self,time:SessionTime)->crate::session::FrameState{
crate::graphics::FrameState{ crate::session::FrameState{
body:self.physics.camera_body(), body:self.physics.camera_body(),
camera:self.physics.camera(), camera:self.physics.camera(),
time:self.timer.time(time), time:self.timer.time(time),
} }
} }
pub fn change_map(&mut self,time:Time,map:&strafesnet_common::map::CompleteMap){ pub fn change_map(&mut self,time:SessionTime,map:&strafesnet_common::map::CompleteMap){
//dump any pending interpolation state //dump any pending interpolation state
if self.mouse_blocking{ if self.mouse_blocking{
self.unblock_mouse(time); self.unblock_mouse(time);
@ -197,7 +186,7 @@ impl MouseInterpolator{
//use the standard input interface so the instructions are written out to bots //use the standard input interface so the instructions are written out to bots
self.handle_instruction(&TimedInstruction{ self.handle_instruction(&TimedInstruction{
time:self.timer.time(time), time,
instruction:Instruction::Input(InputInstruction::ResetAndSpawn( instruction:Instruction::Input(InputInstruction::ResetAndSpawn(
strafesnet_common::gameplay_modes::ModeId::MAIN, strafesnet_common::gameplay_modes::ModeId::MAIN,
strafesnet_common::gameplay_modes::StageId::FIRST, strafesnet_common::gameplay_modes::StageId::FIRST,

View File

@ -1,8 +1,24 @@
// session represents the non-hardware state of the client. // session represents the non-hardware state of the client.
// Ideally it is a deterministic state which is atomically updated by instructions, same as the simulation state. // Ideally it is a deterministic state which is atomically updated by instructions, same as the simulation state.
use strafesnet_common::physics::Time as PhysicsTime;
use strafesnet_common::timer::{Scaled,Timer};
use strafesnet_common::physics::TimeInner as PhysicsTimeInner;
use strafesnet_common::session::TimeInner as SessionTimeInner;
pub struct FrameState{
pub body:crate::physics::Body,
pub camera:crate::physics::PhysicsCamera,
pub time:PhysicsTime,
}
pub struct Simulation{
timer:Timer<Scaled<SessionTimeInner,PhysicsTimeInner>>,
physics:crate::physics::PhysicsContext,
}
pub struct SessionState{ pub struct SessionState{
mouse_interpolator:MouseInterpolator, user_settings:crate::settings::UserSettings,
mouse_interpolator:crate::mouse_interpolator::MouseInterpolator,
//gui:GuiState //gui:GuiState
physics:PhysicsContext, simulation:Simulation,
} }