diff --git a/src/physics.rs b/src/physics.rs index fe952cb..858a9b7 100644 --- a/src/physics.rs +++ b/src/physics.rs @@ -668,7 +668,7 @@ impl PhysicsModel{ } } -#[derive(Debug,Clone,Eq,Hash,PartialEq)] +#[derive(Debug,Clone,Copy,Eq,Hash,PartialEq)] pub struct ContactCollision{ face_id:model_physics::MinkowskiFace, convex_mesh_id:ConvexMeshId, @@ -1300,19 +1300,21 @@ fn run_teleport_behaviour(wormhole:&Option,models =>state.advance_time(ins.time), } match ins.instruction{ - PhysicsInstruction::CollisionStart(c)=>{ - let convex_mesh_id=c.convex_mesh_id(); - match (data.models.attr(convex_mesh_id.model_id),&c){ - (PhysicsCollisionAttributes::Contact{contacting,general},Collision::Contact(contact))=>{ - let mut v=state.body.velocity; + PhysicsInstruction::CollisionStart(collision)=>{ + let convex_mesh_id=collision.convex_mesh_id(); + match (data.models.attr(convex_mesh_id.model_id),&collision){ + (PhysicsCollisionAttributes::Contact{contacting,general},&Collision::Contact(contact))=>{ + let incident_velocity=state.body.velocity; + //add to touching + state.touching.insert(collision); + //clip v + set_velocity(&mut state.body,&state.touching,&data.models,&data.hitbox_mesh,incident_velocity); match &contacting.contact_behaviour{ Some(gameplay_attributes::ContactingBehaviour::Surf)=>println!("I'm surfing!"), Some(gameplay_attributes::ContactingBehaviour::Cling)=>println!("Unimplemented!"), &Some(gameplay_attributes::ContactingBehaviour::Elastic(elasticity))=>{ - //velocity and normal are facing opposite directions so this is inherently negative. - let normal=contact_normal(&data.models,&data.hitbox_mesh,contact); - let d=normal.dot(v)*(Planar64::ONE+Planar64::raw(elasticity as i64+1)); - v+=normal*(d/normal.dot(normal)); + let reflected_velocity=state.body.velocity+(state.body.velocity-incident_velocity)*Planar64::raw(elasticity as i64+1); + set_velocity(&mut state.body,&state.touching,&data.models,&data.hitbox_mesh,reflected_velocity); }, Some(gameplay_attributes::ContactingBehaviour::Ladder(contacting_ladder))=> if let Some(ladder_settings)=&state.style.ladder{ @@ -1320,37 +1322,39 @@ fn run_teleport_behaviour(wormhole:&Option,models //kill v //actually you could do this with a booster attribute :thinking: //it's a little bit different because maybe you want to chain ladders together - v=Planar64Vec3::ZERO;//model.velocity + set_velocity(&mut state.body,&state.touching,&data.models,&data.hitbox_mesh,Planar64Vec3::ZERO);//model.velocity } //ladder walkstate - let (gravity,target_velocity,normal)=ladder_things(ladder_settings,contact,&state.touching,&data.models,&data.hitbox_mesh,&state.style,&state.camera,&state.input_state); - let walk_state=ContactMoveState::ladder(ladder_settings,&state.body,gravity,target_velocity,contact.clone(),normal); + let (gravity,target_velocity,normal)=ladder_things(ladder_settings,&contact,&state.touching,&data.models,&data.hitbox_mesh,&state.style,&state.camera,&state.input_state); + let walk_state=ContactMoveState::ladder(ladder_settings,&state.body,gravity,target_velocity,contact,normal); state.set_move_state(&data,MoveState::Ladder(walk_state)); }, Some(gameplay_attributes::ContactingBehaviour::NoJump)=>todo!("nyi"), None=>if let Some(walk_settings)=&state.style.walk{ - if walk_settings.is_slope_walkable(contact_normal(&data.models,&data.hitbox_mesh,contact),Planar64Vec3::Y){ + if walk_settings.is_slope_walkable(contact_normal(&data.models,&data.hitbox_mesh,&contact),Planar64Vec3::Y){ //ground - let (gravity,target_velocity,normal)=ground_things(walk_settings,contact,&state.touching,&data.models,&data.hitbox_mesh,&state.style,&state.camera,&state.input_state); - let walk_state=ContactMoveState::ground(walk_settings,&state.body,gravity,target_velocity,contact.clone(),normal); + let (gravity,target_velocity,normal)=ground_things(walk_settings,&contact,&state.touching,&data.models,&data.hitbox_mesh,&state.style,&state.camera,&state.input_state); + let walk_state=ContactMoveState::ground(walk_settings,&state.body,gravity,target_velocity,contact,normal); state.set_move_state(&data,MoveState::Walk(walk_state)); } }, } - //check ground - state.touching.insert(c); //I love making functions with 10 arguments to dodge the borrow checker if let Some(mode)=data.modes.get_mode(state.mode_state.get_mode_id()){ run_teleport_behaviour(&general.wormhole,&data.models,mode,&state.style,&data.hitbox_mesh,&mut state.mode_state,&mut state.touching,&mut state.body,convex_mesh_id); } - //flatten v - state.touching.constrain_velocity(&data.models,&data.hitbox_mesh,&mut v); match &general.booster{ Some(booster)=>{ //DELETE THIS when boosters get converted to height machines match booster{ //&gameplay_attributes::Booster::Affine(transform)=>v=transform.transform_point3(v), - &gameplay_attributes::Booster::Velocity(velocity)=>v+=velocity, + &gameplay_attributes::Booster::Velocity(velocity)=>{ + let boosted_velocity=state.body.velocity+velocity; + if set_velocity_cull(&mut state.body,&mut state.touching,&data.models,&data.hitbox_mesh,boosted_velocity){ + //wrong!!! + state.set_move_state(&data,MoveState::Air); + } + }, &gameplay_attributes::Booster::Energy{direction: _,energy: _}=>todo!(), } }, @@ -1359,8 +1363,8 @@ fn run_teleport_behaviour(wormhole:&Option,models if state.style.get_control(Controls::Jump,state.input_state.controls){ if let (Some(jump_settings),Some(walk_state))=(&state.style.jump,state.move_state.get_walk_state()){ let jump_dir=walk_state.jump_direction.direction(&data.models,&data.hitbox_mesh,&walk_state.contact); - v=jump_settings.jumped_velocity(&state.style,jump_dir,v); - if set_velocity_cull(&mut state.body,&mut state.touching,&data.models,&data.hitbox_mesh,v){ + let jumped_velocity=jump_settings.jumped_velocity(&state.style,jump_dir,state.body.velocity); + if set_velocity_cull(&mut state.body,&mut state.touching,&data.models,&data.hitbox_mesh,jumped_velocity){ //wrong!!! state.set_move_state(&data,MoveState::Air); } @@ -1373,20 +1377,21 @@ fn run_teleport_behaviour(wormhole:&Option,models gameplay_attributes::SetTrajectory::Height(_)=>todo!(), gameplay_attributes::SetTrajectory::TargetPointTime { target_point: _, time: _ }=>todo!(), gameplay_attributes::SetTrajectory::TargetPointSpeed { target_point: _, speed: _, trajectory_choice: _ }=>todo!(), - &gameplay_attributes::SetTrajectory::Velocity(velocity)=>v=velocity, + &gameplay_attributes::SetTrajectory::Velocity(velocity)=>{ + if set_velocity_cull(&mut state.body,&mut state.touching,&data.models,&data.hitbox_mesh,velocity){ + //wrong!!! + state.set_move_state(&data,MoveState::Air); + } + }, gameplay_attributes::SetTrajectory::DotVelocity { direction: _, dot: _ }=>todo!(), } }, None=>(), } - //get rid of this garbage - set_velocity(&mut state.body,&state.touching,&data.models,&data.hitbox_mesh,v); - //use a different function????? - //state.move_state.apply_input(&mut state.body,&state.touching,&data.models,&data.hitbox_mesh,&state.style,&state.camera,&state.input_state); }, (PhysicsCollisionAttributes::Intersect{intersecting: _,general},Collision::Intersect(intersect))=>{ //I think that setting the velocity to 0 was preventing surface contacts from entering an infinite loop - state.touching.insert(c); + state.touching.insert(collision); if let Some(mode)=data.modes.get_mode(state.mode_state.get_mode_id()){ run_teleport_behaviour(&general.wormhole,&data.models,mode,&state.style,&data.hitbox_mesh,&mut state.mode_state,&mut state.touching,&mut state.body,convex_mesh_id); } @@ -1394,16 +1399,24 @@ fn run_teleport_behaviour(wormhole:&Option,models _=>panic!("invalid pair"), } }, - PhysicsInstruction::CollisionEnd(c)=>{ - match data.models.attr(c.convex_mesh_id().model_id){ - PhysicsCollisionAttributes::Contact{contacting:_,general:_}=>{ - state.touching.remove(&c);//remove contact before calling contact_constrain_acceleration + PhysicsInstruction::CollisionEnd(collision)=>{ + match (data.models.attr(collision.convex_mesh_id().model_id),&collision){ + (PhysicsCollisionAttributes::Contact{contacting:_,general:_},&Collision::Contact(contact))=>{ + state.touching.remove(&collision);//remove contact before calling contact_constrain_acceleration //check ground //TODO lol + match state.move_state.get_walk_state(){ + //did you stop touching the thing you were walking on? + Some(walk_state)=>if walk_state.contact==contact{ + state.set_move_state(&data,MoveState::Air); + }, + None=>(), + } }, - PhysicsCollisionAttributes::Intersect{intersecting:_,general:_}=>{ - state.touching.remove(&c); + (PhysicsCollisionAttributes::Intersect{intersecting: _,general:_},Collision::Intersect(_))=>{ + state.touching.remove(&collision); }, + _=>panic!("invalid pair"), } }, PhysicsInstruction::StrafeTick=>{ @@ -1499,6 +1512,7 @@ fn run_teleport_behaviour(wormhole:&Option,models set_position(&mut state.body,&mut state.touching,spawn_point); set_velocity(&mut state.body,&state.touching,&data.models,&data.hitbox_mesh,Planar64Vec3::ZERO); state.set_move_state(&data,MoveState::Air); + b_refresh_walk_target=false; }, PhysicsInputInstruction::PracticeFly=>{ match &state.move_state{ @@ -1509,6 +1523,7 @@ fn run_teleport_behaviour(wormhole:&Option,models state.set_move_state(&data,MoveState::Fly); }, } + b_refresh_walk_target=false; }, PhysicsInputInstruction::Idle=>{b_refresh_walk_target=false;},//literally idle! }