You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Describe the bug
During development we found an issue with floating point precision during calculating collisions and intersections when moving inside the Game's physics engine.
We wrote tests in tests/de/gurkenlabs/litiengine/physics/CollisionResolvingTests.java to ensure consistent movements. However, one of the tests will fail if I provide the distance constant as it is (i.e., a distance to trigger a diagonal movement of 10 units each on the X and Y axis), but it will pass if I subtract a marginal value (i.e., 1e-14).
The issue is that due to the floating point precision it miscalculates an intersection to exist where there should not be any...
There is a parameterized test which passes for the same functionality but in different directions. Most relevant would probably be the one in direction right which has a negated sign compared to the one with issues.
I think I'm experiencing a similar issue in my game. When I try to move my player at a diagonal against a wall, the player sometimes gets "stuck" inside.
Here are some numbers for when I try to move diagonally to the right into a wall:
wall's x = 485.0
player's target x (where the player is trying to move) = 486.1313708667572
intersection width (as calculated by Rectangle2D.createIntersection in PhysicsEngine.getIntersection) = 1.1313708667571518
difference = 485.0000000000000482
difference when stored in double = 485.00000000000006
So, the resolved x is 0.00000000000006 too far to the right and thus the player gets "stuck" inside the wall. By "stuck," I mean when I'm in this state, the player cannot move up and down (or to the right, but there's a wall there, so duh). I can move to the left, still, and get out of this state. But it seems weird and inconsistent to the player because it only happens sometimes and only on some of the walls.
In case anyone runs into this issue, I've been using the following work-around:
@Override
public void setLocation(final Point2D location) {
double subPixelX = location.getX() % 1;
if (subPixelX > 0 && subPixelX < 0.0000000000001) { // Round down if we're close enough to the floor.
location.setLocation(Math.floor(location.getX()), location.getY());
} else if (subPixelX < 1 && subPixelX > 0.999999999999) { // Round up if we're close enough to the ceiling.
location.setLocation(Math.ceil(location.getX()), location.getY());
}
double subPixelY = location.getY() % 1;
if (subPixelY > 0 && subPixelY < 0.0000000000001) { // Round down if we're close enough to the floor.
location.setLocation(location.getX(), Math.floor(location.getY()));
} else if (subPixelY < 1 && subPixelY > 0.999999999999) { // Round up if we're close enough to the ceiling.
location.setLocation(location.getX(), Math.ceil(location.getY()));
}
super.setLocation(location);
}
It might not be the most efficient thing in the world. I wrote it a year ago. But it's just checking for the condition I described in my last comment and rounding the x/y location as-needed. I have this in my Player class overriding Creature.SetLocation(). Sometimes you still can't move diagonally into walls, but you don't get stuck in them anymore.
Describe the bug
During development we found an issue with floating point precision during calculating collisions and intersections when moving inside the Game's physics engine.
We wrote tests in
tests/de/gurkenlabs/litiengine/physics/CollisionResolvingTests.java
to ensure consistent movements. However, one of the tests will fail if I provide the distance constant as it is (i.e., a distance to trigger a diagonal movement of 10 units each on the X and Y axis), but it will pass if I subtract a marginal value (i.e.,1e-14
).The issue is that due to the floating point precision it miscalculates an intersection to exist where there should not be any...
There is a parameterized test which passes for the same functionality but in different directions. Most relevant would probably be the one in direction
right
which has a negated sign compared to the one with issues.Stack Trace
Failing Test Error Log
To Reproduce
Steps to reproduce the behavior:
tests/de/gurkenlabs/litiengine/physics/CollisionResolvingTests.java
testCollidingMoveSlideDown()
move()
in the act part with the constantMOVE_10X10Y_DISTANCE
without subtracting anything from itExpected behavior
The test passes with a target location at the expected position.
Your System:
Additional context
The issue was found and adressed in pull requests 397 and 398. Refer to the comments there for further details.
The text was updated successfully, but these errors were encountered: