mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Properly propagate velocity steps during airship collision to avoid falling through airships
This commit is contained in:
parent
26c9fd63ae
commit
f768c3f853
@ -9,7 +9,7 @@ use vek::Vec2;
|
|||||||
|
|
||||||
// Gravity is 9.81 * 4, so this makes gravity equal to .15
|
// Gravity is 9.81 * 4, so this makes gravity equal to .15
|
||||||
const GLIDE_ANTIGRAV: f32 = crate::consts::GRAVITY * 0.90;
|
const GLIDE_ANTIGRAV: f32 = crate::consts::GRAVITY * 0.90;
|
||||||
const GLIDE_ACCEL: f32 = 8.0;
|
const GLIDE_ACCEL: f32 = 6.0;
|
||||||
const GLIDE_SPEED: f32 = 16.0;
|
const GLIDE_SPEED: f32 = 16.0;
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize, Eq, Hash)]
|
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize, Eq, Hash)]
|
||||||
@ -40,13 +40,7 @@ impl CharacterBehavior for Data {
|
|||||||
handle_climb(&data, &mut update);
|
handle_climb(&data, &mut update);
|
||||||
|
|
||||||
// Move player according to movement direction vector
|
// Move player according to movement direction vector
|
||||||
update.vel.0 += Vec2::broadcast(data.dt.0)
|
update.vel.0 += Vec2::broadcast(data.dt.0) * data.inputs.move_dir * GLIDE_ACCEL;
|
||||||
* data.inputs.move_dir
|
|
||||||
* if data.vel.0.magnitude_squared() < GLIDE_SPEED.powi(2) {
|
|
||||||
GLIDE_ACCEL
|
|
||||||
} else {
|
|
||||||
0.0
|
|
||||||
};
|
|
||||||
|
|
||||||
// Determine orientation vector from movement direction vector
|
// Determine orientation vector from movement direction vector
|
||||||
let horiz_vel = Vec2::<f32>::from(update.vel.0);
|
let horiz_vel = Vec2::<f32>::from(update.vel.0);
|
||||||
@ -56,7 +50,7 @@ impl CharacterBehavior for Data {
|
|||||||
|
|
||||||
// Apply Glide antigrav lift
|
// Apply Glide antigrav lift
|
||||||
let horiz_speed_sq = horiz_vel.magnitude_squared();
|
let horiz_speed_sq = horiz_vel.magnitude_squared();
|
||||||
if horiz_speed_sq < GLIDE_SPEED.powi(2) && update.vel.0.z < 0.0 {
|
if update.vel.0.z < 0.0 {
|
||||||
let lift = (GLIDE_ANTIGRAV + update.vel.0.z.powi(2) * 0.15)
|
let lift = (GLIDE_ANTIGRAV + update.vel.0.z.powi(2) * 0.15)
|
||||||
* (horiz_speed_sq * f32::powf(0.075, 2.0)).clamp(0.2, 1.0);
|
* (horiz_speed_sq * f32::powf(0.075, 2.0)).clamp(0.2, 1.0);
|
||||||
|
|
||||||
|
@ -17,8 +17,8 @@ use std::time::Duration;
|
|||||||
use vek::*;
|
use vek::*;
|
||||||
|
|
||||||
pub const MOVEMENT_THRESHOLD_VEL: f32 = 3.0;
|
pub const MOVEMENT_THRESHOLD_VEL: f32 = 3.0;
|
||||||
const BASE_HUMANOID_AIR_ACCEL: f32 = 0.5;
|
const BASE_HUMANOID_AIR_ACCEL: f32 = 2.0;
|
||||||
const BASE_FLIGHT_ACCEL: f32 = 3.5;
|
const BASE_FLIGHT_ACCEL: f32 = 2.0;
|
||||||
const BASE_HUMANOID_WATER_ACCEL: f32 = 150.0;
|
const BASE_HUMANOID_WATER_ACCEL: f32 = 150.0;
|
||||||
const BASE_HUMANOID_WATER_SPEED: f32 = 180.0;
|
const BASE_HUMANOID_WATER_SPEED: f32 = 180.0;
|
||||||
// const BASE_HUMANOID_CLIMB_ACCEL: f32 = 10.0;
|
// const BASE_HUMANOID_CLIMB_ACCEL: f32 = 10.0;
|
||||||
|
@ -411,7 +411,6 @@ impl<'a> PhysicsData<'a> {
|
|||||||
)| {
|
)| {
|
||||||
// defer the writes of positions to allow an inner loop over terrain-like
|
// defer the writes of positions to allow an inner loop over terrain-like
|
||||||
// entities
|
// entities
|
||||||
let old_pos = *pos;
|
|
||||||
let mut pos = *pos;
|
let mut pos = *pos;
|
||||||
let mut vel = *vel;
|
let mut vel = *vel;
|
||||||
if sticky.is_some() && physics_state.on_surface().is_some() {
|
if sticky.is_some() && physics_state.on_surface().is_some() {
|
||||||
@ -469,6 +468,8 @@ impl<'a> PhysicsData<'a> {
|
|||||||
Vec3::zero()
|
Vec3::zero()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let mut tgt_pos = pos.0 + pos_delta;
|
||||||
|
|
||||||
let was_on_ground = physics_state.on_ground;
|
let was_on_ground = physics_state.on_ground;
|
||||||
|
|
||||||
match &collider {
|
match &collider {
|
||||||
@ -481,21 +482,22 @@ impl<'a> PhysicsData<'a> {
|
|||||||
let radius = collider.get_radius() * scale * 0.1;
|
let radius = collider.get_radius() * scale * 0.1;
|
||||||
let (z_min, z_max) = collider.get_z_limits(scale);
|
let (z_min, z_max) = collider.get_z_limits(scale);
|
||||||
|
|
||||||
|
let mut cpos = pos;
|
||||||
let cylinder = (radius, z_min, z_max);
|
let cylinder = (radius, z_min, z_max);
|
||||||
cylinder_voxel_collision(
|
cylinder_voxel_collision(
|
||||||
cylinder,
|
cylinder,
|
||||||
&*read.terrain,
|
&*read.terrain,
|
||||||
entity,
|
entity,
|
||||||
&mut pos,
|
&mut cpos,
|
||||||
pos_delta,
|
tgt_pos,
|
||||||
&mut vel,
|
&mut vel,
|
||||||
&mut physics_state,
|
&mut physics_state,
|
||||||
Vec3::zero(),
|
Vec3::zero(),
|
||||||
&read.dt,
|
&read.dt,
|
||||||
true,
|
|
||||||
was_on_ground,
|
was_on_ground,
|
||||||
|entity, vel| land_on_grounds.push((entity, vel)),
|
|entity, vel| land_on_grounds.push((entity, vel)),
|
||||||
);
|
);
|
||||||
|
tgt_pos = cpos.0;
|
||||||
},
|
},
|
||||||
Collider::Box {
|
Collider::Box {
|
||||||
radius,
|
radius,
|
||||||
@ -508,20 +510,21 @@ impl<'a> PhysicsData<'a> {
|
|||||||
let z_max = z_max.clamped(1.2, 1.95) * scale;
|
let z_max = z_max.clamped(1.2, 1.95) * scale;
|
||||||
|
|
||||||
let cylinder = (radius, z_min, z_max);
|
let cylinder = (radius, z_min, z_max);
|
||||||
|
let mut cpos = pos;
|
||||||
cylinder_voxel_collision(
|
cylinder_voxel_collision(
|
||||||
cylinder,
|
cylinder,
|
||||||
&*read.terrain,
|
&*read.terrain,
|
||||||
entity,
|
entity,
|
||||||
&mut pos,
|
&mut cpos,
|
||||||
pos_delta,
|
tgt_pos,
|
||||||
&mut vel,
|
&mut vel,
|
||||||
&mut physics_state,
|
&mut physics_state,
|
||||||
Vec3::zero(),
|
Vec3::zero(),
|
||||||
&read.dt,
|
&read.dt,
|
||||||
true,
|
|
||||||
was_on_ground,
|
was_on_ground,
|
||||||
|entity, vel| land_on_grounds.push((entity, vel)),
|
|entity, vel| land_on_grounds.push((entity, vel)),
|
||||||
);
|
);
|
||||||
|
tgt_pos = cpos.0;
|
||||||
},
|
},
|
||||||
Collider::Point => {
|
Collider::Point => {
|
||||||
let (dist, block) = read
|
let (dist, block) = read
|
||||||
@ -567,6 +570,8 @@ impl<'a> PhysicsData<'a> {
|
|||||||
.get(pos.0.map(|e| e.floor() as i32))
|
.get(pos.0.map(|e| e.floor() as i32))
|
||||||
.ok()
|
.ok()
|
||||||
.and_then(|vox| vox.is_liquid().then_some(1.0));
|
.and_then(|vox| vox.is_liquid().then_some(1.0));
|
||||||
|
|
||||||
|
tgt_pos = pos.0;
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -632,7 +637,8 @@ impl<'a> PhysicsData<'a> {
|
|||||||
let mut physics_state_delta = physics_state.clone();
|
let mut physics_state_delta = physics_state.clone();
|
||||||
// deliberately don't use scale yet here, because the 11.0/0.8
|
// deliberately don't use scale yet here, because the 11.0/0.8
|
||||||
// thing is in the comp::Scale for visual reasons
|
// thing is in the comp::Scale for visual reasons
|
||||||
let wpos = pos.0;
|
let mut cpos = pos;
|
||||||
|
let wpos = cpos.0;
|
||||||
let transform_from =
|
let transform_from =
|
||||||
Mat4::<f32>::translation_3d(pos_other.0 - wpos)
|
Mat4::<f32>::translation_3d(pos_other.0 - wpos)
|
||||||
* Mat4::from(ori_other.0)
|
* Mat4::from(ori_other.0)
|
||||||
@ -640,20 +646,19 @@ impl<'a> PhysicsData<'a> {
|
|||||||
let transform_to = transform_from.inverted();
|
let transform_to = transform_from.inverted();
|
||||||
let ori_from = Mat4::from(ori_other.0);
|
let ori_from = Mat4::from(ori_other.0);
|
||||||
let ori_to = ori_from.inverted();
|
let ori_to = ori_from.inverted();
|
||||||
pos.0 = transform_to.mul_point(Vec3::zero());
|
cpos.0 = transform_to.mul_point(Vec3::zero());
|
||||||
vel.0 = ori_to.mul_direction(vel.0 - vel_other.0);
|
vel.0 = ori_to.mul_direction(vel.0 - vel_other.0);
|
||||||
let cylinder = (radius, z_min, z_max);
|
let cylinder = (radius, z_min, z_max);
|
||||||
cylinder_voxel_collision(
|
cylinder_voxel_collision(
|
||||||
cylinder,
|
cylinder,
|
||||||
&voxel_collider.dyna,
|
&voxel_collider.dyna,
|
||||||
entity,
|
entity,
|
||||||
&mut pos,
|
&mut cpos,
|
||||||
transform_to.mul_direction(pos_delta),
|
transform_to.mul_point(tgt_pos - wpos),
|
||||||
&mut vel,
|
&mut vel,
|
||||||
&mut physics_state_delta,
|
&mut physics_state_delta,
|
||||||
ori_to.mul_direction(vel_other.0),
|
ori_to.mul_direction(vel_other.0),
|
||||||
&read.dt,
|
&read.dt,
|
||||||
false,
|
|
||||||
was_on_ground,
|
was_on_ground,
|
||||||
|entity, vel| {
|
|entity, vel| {
|
||||||
land_on_grounds
|
land_on_grounds
|
||||||
@ -661,8 +666,9 @@ impl<'a> PhysicsData<'a> {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
pos.0 = transform_from.mul_point(pos.0) + wpos;
|
cpos.0 = transform_from.mul_point(cpos.0) + wpos;
|
||||||
vel.0 = ori_from.mul_direction(vel.0) + vel_other.0;
|
vel.0 = ori_from.mul_direction(vel.0) + vel_other.0;
|
||||||
|
tgt_pos = cpos.0;
|
||||||
|
|
||||||
// union in the state updates, so that the state isn't just based on
|
// union in the state updates, so that the state isn't just based on
|
||||||
// the most recent terrain that collision was attempted with
|
// the most recent terrain that collision was attempted with
|
||||||
@ -691,8 +697,9 @@ impl<'a> PhysicsData<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if pos != old_pos {
|
|
||||||
pos_writes.push((entity, pos));
|
if tgt_pos != pos.0 {
|
||||||
|
pos_writes.push((entity, Pos(tgt_pos)));
|
||||||
}
|
}
|
||||||
if vel != old_vel {
|
if vel != old_vel {
|
||||||
vel_writes.push((entity, vel));
|
vel_writes.push((entity, vel));
|
||||||
@ -771,12 +778,11 @@ fn cylinder_voxel_collision<'a, T: BaseVol<Vox = Block> + ReadVol>(
|
|||||||
terrain: &'a T,
|
terrain: &'a T,
|
||||||
entity: Entity,
|
entity: Entity,
|
||||||
pos: &mut Pos,
|
pos: &mut Pos,
|
||||||
mut pos_delta: Vec3<f32>,
|
tgt_pos: Vec3<f32>,
|
||||||
vel: &mut Vel,
|
vel: &mut Vel,
|
||||||
physics_state: &mut PhysicsState,
|
physics_state: &mut PhysicsState,
|
||||||
ground_vel: Vec3<f32>,
|
ground_vel: Vec3<f32>,
|
||||||
dt: &DeltaTime,
|
dt: &DeltaTime,
|
||||||
apply_velocity_step: bool, // Stupid hack
|
|
||||||
was_on_ground: bool,
|
was_on_ground: bool,
|
||||||
mut land_on_ground: impl FnMut(Entity, Vel),
|
mut land_on_ground: impl FnMut(Entity, Vel),
|
||||||
) {
|
) {
|
||||||
@ -859,6 +865,8 @@ fn cylinder_voxel_collision<'a, T: BaseVol<Vox = Block> + ReadVol>(
|
|||||||
let mut on_ceiling = false;
|
let mut on_ceiling = false;
|
||||||
let mut attempts = 0; // Don't loop infinitely here
|
let mut attempts = 0; // Don't loop infinitely here
|
||||||
|
|
||||||
|
let mut pos_delta = tgt_pos - pos.0;
|
||||||
|
|
||||||
// Don't jump too far at once
|
// Don't jump too far at once
|
||||||
let increments = (pos_delta.map(|e| e.abs()).reduce_partial_max() / 0.3)
|
let increments = (pos_delta.map(|e| e.abs()).reduce_partial_max() / 0.3)
|
||||||
.ceil()
|
.ceil()
|
||||||
@ -866,9 +874,7 @@ fn cylinder_voxel_collision<'a, T: BaseVol<Vox = Block> + ReadVol>(
|
|||||||
let old_pos = pos.0;
|
let old_pos = pos.0;
|
||||||
fn block_true(_: &Block) -> bool { true }
|
fn block_true(_: &Block) -> bool { true }
|
||||||
for _ in 0..increments as usize {
|
for _ in 0..increments as usize {
|
||||||
if apply_velocity_step {
|
pos.0 += pos_delta / increments;
|
||||||
pos.0 += pos_delta / increments;
|
|
||||||
}
|
|
||||||
|
|
||||||
const MAX_ATTEMPTS: usize = 16;
|
const MAX_ATTEMPTS: usize = 16;
|
||||||
|
|
||||||
@ -1069,7 +1075,9 @@ fn cylinder_voxel_collision<'a, T: BaseVol<Vox = Block> + ReadVol>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if physics_state.on_ground || physics_state.on_wall.is_some() {
|
if physics_state.on_ground || physics_state.on_wall.is_some() {
|
||||||
vel.0 *= (1.0 - FRIC_GROUND.min(1.0)).powf(dt.0 * 60.0);
|
if physics_state.on_ground {
|
||||||
|
vel.0 *= (1.0 - FRIC_GROUND.min(1.0)).powf(dt.0 * 60.0);
|
||||||
|
}
|
||||||
physics_state.ground_vel = ground_vel;
|
physics_state.ground_vel = ground_vel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user