Collision: fix 'touching_ground' detection at high dtime
This commit is contained in:
parent
c9085cdd81
commit
9a3b842221
@ -109,6 +109,8 @@ CollisionAxis axisAlignedCollision(
|
||||
|
||||
if (speed.Y) {
|
||||
distance = relbox.MaxEdge.Y - relbox.MinEdge.Y;
|
||||
// FIXME: The dtime calculation is inaccurate without acceleration information.
|
||||
// Exact formula: `dtime = (-vel ± sqrt(vel² + 2 * acc * distance)) / acc`
|
||||
*dtime = distance / std::abs(speed.Y);
|
||||
time = std::max(*dtime, 0.0f);
|
||||
|
||||
@ -526,15 +528,22 @@ collisionMoveResult collisionMoveSimple(Environment *env, IGameDef *gamedef,
|
||||
speed_f->X *= bounce;
|
||||
} else {
|
||||
speed_f->X = 0;
|
||||
accel_f.X = 0;
|
||||
accel_f.X = 0; // avoid colliding in the next interations
|
||||
}
|
||||
result.collides = true;
|
||||
} else if (nearest_collided == COLLISION_AXIS_Y) {
|
||||
if(bounce < -1e-4 && fabsf(speed_f->Y) > BS * 3) {
|
||||
if (bounce < -1e-4 && fabsf(speed_f->Y) > BS * 3) {
|
||||
speed_f->Y *= bounce;
|
||||
} else {
|
||||
if (speed_f->Y < 0.0f) {
|
||||
// FIXME: This code is necessary until `axisAlignedCollision` takes acceleration
|
||||
// into consideration for the time calculation. Otherwise, the colliding faces
|
||||
// never line up, especially at high step (dtime) intervals.
|
||||
result.touching_ground = true;
|
||||
result.standing_on_object = nearest_info.isObject();
|
||||
}
|
||||
speed_f->Y = 0;
|
||||
accel_f.Y = 0;
|
||||
accel_f.Y = 0; // avoid colliding in the next interations
|
||||
}
|
||||
result.collides = true;
|
||||
} else if (nearest_collided == COLLISION_AXIS_Z) {
|
||||
@ -542,7 +551,7 @@ collisionMoveResult collisionMoveSimple(Environment *env, IGameDef *gamedef,
|
||||
speed_f->Z *= bounce;
|
||||
} else {
|
||||
speed_f->Z = 0;
|
||||
accel_f.Z = 0;
|
||||
accel_f.Z = 0; // avoid colliding in the next interations
|
||||
}
|
||||
result.collides = true;
|
||||
} else {
|
||||
@ -592,10 +601,10 @@ collisionMoveResult collisionMoveSimple(Environment *env, IGameDef *gamedef,
|
||||
box.MaxEdge += *pos_f;
|
||||
}
|
||||
if (std::fabs(cbox.MaxEdge.Y - box.MinEdge.Y) < 0.05f) {
|
||||
// This is code is technically only required if `box_info.is_step_up == true`.
|
||||
// However, players rely on this check/condition to climb stairs faster. See PR #10587.
|
||||
result.touching_ground = true;
|
||||
|
||||
if (box_info.isObject())
|
||||
result.standing_on_object = true;
|
||||
result.standing_on_object = box_info.isObject();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user