make a distinction between restart and spawning

This commit is contained in:
Quaternions 2024-08-01 12:57:58 -07:00
parent 755adeaefd
commit e47d152af2
3 changed files with 44 additions and 11 deletions

View File

@ -42,7 +42,8 @@ pub enum PhysicsInputInstruction{
SetMoveForward(bool), SetMoveForward(bool),
SetJump(bool), SetJump(bool),
SetZoom(bool), SetZoom(bool),
Reset, Restart,
Spawn(gameplay_modes::ModeId,StageId),
Idle, Idle,
//Idle: there were no input events, but the simulation is safe to advance to this timestep //Idle: there were no input events, but the simulation is safe to advance to this timestep
//for interpolation / networking / playback reasons, most playback heads will always want //for interpolation / networking / playback reasons, most playback heads will always want
@ -963,6 +964,11 @@ impl PhysicsState{
fn clear(&mut self){ fn clear(&mut self){
self.touching.clear(); self.touching.clear();
} }
fn reset_to_default(&mut self){
let mut new_state=Self::default();
new_state.camera.sensitivity=self.camera.sensitivity;
*self=new_state;
}
fn next_move_instruction(&self)->Option<TimedInstruction<PhysicsInternalInstruction>>{ fn next_move_instruction(&self)->Option<TimedInstruction<PhysicsInternalInstruction>>{
self.move_state.next_move_instruction(&self.style.strafe,self.time) self.move_state.next_move_instruction(&self.style.strafe,self.time)
} }
@ -1059,10 +1065,16 @@ impl PhysicsContext{
instruction:PhysicsInputInstruction::SetSensitivity(user_settings.calculate_sensitivity()), instruction:PhysicsInputInstruction::SetSensitivity(user_settings.calculate_sensitivity()),
}); });
} }
pub fn restart(&mut self){
self.run_input_instruction(TimedInstruction{
time:self.state.time,
instruction:PhysicsInputInstruction::Restart,
});
}
pub fn spawn(&mut self){ pub fn spawn(&mut self){
self.run_input_instruction(TimedInstruction{ self.run_input_instruction(TimedInstruction{
time:self.state.time, time:self.state.time,
instruction:PhysicsInputInstruction::Reset, instruction:PhysicsInputInstruction::Spawn(gameplay_modes::ModeId::MAIN,StageId::FIRST),
}); });
} }
pub const fn output(&self)->PhysicsOutputState{ pub const fn output(&self)->PhysicsOutputState{
@ -1530,7 +1542,8 @@ fn atomic_input_instruction(state:&mut PhysicsState,data:&PhysicsData,ins:TimedI
//the body may as well be a quantum wave function //the body may as well be a quantum wave function
//as far as these instruction are concerned (they don't care where it is) //as far as these instruction are concerned (they don't care where it is)
PhysicsInputInstruction::SetSensitivity(..) PhysicsInputInstruction::SetSensitivity(..)
|PhysicsInputInstruction::Reset |PhysicsInputInstruction::Restart
|PhysicsInputInstruction::Spawn(..)
|PhysicsInputInstruction::SetZoom(..) |PhysicsInputInstruction::SetZoom(..)
|PhysicsInputInstruction::Idle=>false, |PhysicsInputInstruction::Idle=>false,
//these controls only update the body if you are on the ground //these controls only update the body if you are on the ground
@ -1593,18 +1606,26 @@ fn atomic_input_instruction(state:&mut PhysicsState,data:&PhysicsData,ins:TimedI
state.input_state.set_control(Controls::Zoom,s); state.input_state.set_control(Controls::Zoom,s);
b_refresh_walk_target=false; b_refresh_walk_target=false;
}, },
PhysicsInputInstruction::Reset=>{ PhysicsInputInstruction::Restart=>{
//it matters which of these runs first, but I have not thought it through yet as it doesn't matter yet //totally reset physics state
state.mode_state.clear(); state.reset_to_default();
state.mode_state.set_stage_id(gameplay_modes::StageId::FIRST); //spawn at start zone
let spawn_point=data.modes.get_mode(state.mode_state.get_mode_id()).map(|mode| let spawn_point=data.modes.get_mode(state.mode_state.get_mode_id()).map(|mode|
//TODO: spawn at the bottom of the start zone plus the hitbox size //TODO: spawn at the bottom of the start zone plus the hitbox size
//TODO: set camera andles to face the same way as the start zone
data.models.model(mode.get_start().into()).transform.vertex.translation data.models.model(mode.get_start().into()).transform.vertex.translation
).unwrap_or(Planar64Vec3::ZERO); ).unwrap_or(Planar64Vec3::ZERO);
set_position(&mut state.body,&mut state.touching,spawn_point); set_position(&mut state.body,&mut state.touching,spawn_point);
set_velocity(&mut state.body,&state.touching,&data.models,&data.hitbox_mesh,Planar64Vec3::ZERO); set_velocity(&mut state.body,&state.touching,&data.models,&data.hitbox_mesh,Planar64Vec3::ZERO);
state.set_move_state(data,MoveState::Air); state.set_move_state(data,MoveState::Air);
b_refresh_walk_target=false; b_refresh_walk_target=false;
}
PhysicsInputInstruction::Spawn(mode_id,stage_id)=>{
//spawn at a particular stage
if let Some(mode)=data.modes.get_mode(mode_id){
teleport_to_spawn(&mut state.body,&mut state.touching,&state.style,&data.hitbox_mesh,mode,&data.models,stage_id);
}
b_refresh_walk_target=false;
}, },
PhysicsInputInstruction::PracticeFly=>{ PhysicsInputInstruction::PracticeFly=>{
match &state.move_state{ match &state.move_state{

View File

@ -12,7 +12,8 @@ pub enum InputInstruction{
MoveForward(bool), MoveForward(bool),
Jump(bool), Jump(bool),
Zoom(bool), Zoom(bool),
Reset, Restart,
Spawn(strafesnet_common::gameplay_modes::ModeId,strafesnet_common::gameplay_modes::StageId),
PracticeFly, PracticeFly,
} }
pub enum Instruction{ pub enum Instruction{
@ -68,7 +69,8 @@ impl MouseInterpolator{
&InputInstruction::MoveDown(s)=>Some(PhysicsInputInstruction::SetMoveDown(s)), &InputInstruction::MoveDown(s)=>Some(PhysicsInputInstruction::SetMoveDown(s)),
&InputInstruction::Jump(s)=>Some(PhysicsInputInstruction::SetJump(s)), &InputInstruction::Jump(s)=>Some(PhysicsInputInstruction::SetJump(s)),
&InputInstruction::Zoom(s)=>Some(PhysicsInputInstruction::SetZoom(s)), &InputInstruction::Zoom(s)=>Some(PhysicsInputInstruction::SetZoom(s)),
InputInstruction::Reset=>Some(PhysicsInputInstruction::Reset), &InputInstruction::Spawn(mode_id,stage_id)=>Some(PhysicsInputInstruction::Spawn(mode_id,stage_id)),
InputInstruction::Restart=>Some(PhysicsInputInstruction::Restart),
InputInstruction::PracticeFly=>Some(PhysicsInputInstruction::PracticeFly), InputInstruction::PracticeFly=>Some(PhysicsInputInstruction::PracticeFly),
}, },
Instruction::GenerateModels(_)=>Some(PhysicsInputInstruction::Idle), Instruction::GenerateModels(_)=>Some(PhysicsInputInstruction::Idle),
@ -150,6 +152,12 @@ pub fn new(mut physics:crate::physics::PhysicsContext,mut graphics_worker:crate:
}, },
Instruction::GenerateModels(map)=>{ Instruction::GenerateModels(map)=>{
physics.generate_models(&map); physics.generate_models(&map);
//important!
//bots will not work properly without this exact restart + spawn setup
//reset the physics state to start a new run on the new map
physics.restart();
//generate a spawn event so bots work properly on the first run
//no run started so does not invalidate the run
physics.spawn(); physics.spawn();
graphics_worker.send(crate::graphics_worker::Instruction::GenerateModels(map)).unwrap(); graphics_worker.send(crate::graphics_worker::Instruction::GenerateModels(map)).unwrap();
}, },

View File

@ -107,7 +107,11 @@ impl WindowContext<'_>{
"e"=>Some(InputInstruction::MoveUp(s)), "e"=>Some(InputInstruction::MoveUp(s)),
"q"=>Some(InputInstruction::MoveDown(s)), "q"=>Some(InputInstruction::MoveDown(s)),
"z"=>Some(InputInstruction::Zoom(s)), "z"=>Some(InputInstruction::Zoom(s)),
"r"=>if s{Some(InputInstruction::Reset)}else{None}, "r"=>if s{
//mouse needs to be reset since the position is absolute
self.mouse=crate::physics::MouseState::default();
Some(InputInstruction::Restart)
}else{None},
"f"=>if s{Some(InputInstruction::PracticeFly)}else{None}, "f"=>if s{Some(InputInstruction::PracticeFly)}else{None},
_=>None, _=>None,
}, },
@ -233,4 +237,4 @@ impl<'a> WindowContextSetup<'a>{
} }
}) })
} }
} }