I've been at this for 2-3 weeks now and I still can't manage to have a proper collision detection. I have created a maze using rectangles. I want my object (which is in a Rectangle) to stop whenever my object collides with any wall and be able to move anywhere (or slide down a wall). My walls (the rectangles) have negative coordinates like the following:
shapeRenderer.rect(0.9f, 12, 1.15f, 0, Color.RED, Color.RED, Color.RED, Color.RED); //NORTH
shapeRenderer.rect(1, 12, 0, -1.05f, Color.RED, Color.RED, Color.RED, Color.RED); // WEST
shapeRenderer.rect(2, 12, 0, -1.05f, Color.RED, Color.RED, Color.RED, Color.RED); // EAST
shapeRenderer.rect(0.9f, 11, 1.15f, 0, Color.RED, Color.RED, Color.RED, Color.RED); // SOUTH
I'm currently using an overlaps method that I've found in SO. Here's the method that's in my CollisionManager class:
private boolean overlaps (Rectangle collision, Rectangle wall) {
return Math.min(collision.x, collision.x + collision.width)
< Math.max(wall.x, wall.x + wall.width)
&& Math.max(collision.x, collision.x + collision.width)
> Math.min(wall.x, wall.x + wall.width)
&& Math.min(collision.y, collision.y + collision.height)
< Math.max(wall.y, wall.y + wall.height)
&& Math.max(collision.y, collision.y + collision.height)
> Math.min(wall.y, wall.y + wall.height);
}
I have a function which saves all position moves made by the object. Thus, when a collision occurs, the object restores to the previous move before the last move (since the last move is when the collision occured) (example below):
private void overlapsTop(Entity object, Rectangle wall){
Rectangle r = new Rectangle();
if(spritePositions.size() != 0){
r = spritePositions.get(spritePositions.size()-1);
}
object.update(r.x, r.y, r.width, r.height);
object.getObject().setBounds(r.x, r.y, r.width, r.height);
spritePositions.clear();
}
Additional information: I'm moving my object like this:
public void moveRight(){
position.x += 1f;
update();
}
public void update(){
boundingRectangle.set(position.x, position.y, object.getWidth(), object.getHeight());
}
Where I'm stuck is my overlaps function (the one I've found in SO). It works most cases; yet, for example, if the object moves near a wall on the right and touches it, the function returns true and everything gets executed. But let's say if I slide along the wall and move directly down and that there are no walls, the object stops at one point because it detects a collision between the bottom of the object and the top of a wall (when there's none) and a collision between the right of the object and the left of a wall.
I'm trying to find another solution for this. I just want my object to stop at any wall and be able to move (or slide down a wall) without suspecting that there might be a collision where there are no walls nearby. I feel that I'm very close to a solution, but I would need a little bit of extra help.
UPDATE
I've updated the moveRight function and the update function. @Adrian Shum and @Matthew Mark Miller I've made everything now with an integer (meaning instead of 0.01f, I use 1f).
Thus the following code that I use to move the object is like this:
if(Gdx.input.isKeyPressed(Keys.RIGHT)){
if(collisionManager.canSpriteNotMoveRight(object)){
object.stopGoingRight();
}else{
object.moveRight();
}
}
In my collisionManager class, the function stopGoingRight is the following:
public void stopGoingRight(){
position.x -= 1f;
update();
}
So far, so good. When the object collides with the wall, the object stops and bounces back. That's good. But I have another problem (which is irritating) that I'll try to describe the best I can. If, for example, I keep moving the object up to a wall, the object will bounce back many times from that wall; if I stop pressing the up key, the object will sometimes stay stuck within the wall. Thus what happen is when I press the down key, it'll go up instead of going down (or if I press left, the object will go right instead of going left) because the overlaps function gets executed (since both object and the wall intersect).
Is there a way for me to solve this? It seems as though Libgdx isn't perfectly well-suited to handle this kind of collision detection, but I'm just far into deep in building my game right now.
Your collision algorithm seems wordy but correct (Wordy because the min of x, x+ width is always just x as width must be >= 0, and the inverse is true for max).
Have you considered the possibility that it's a floating point precision issue? E.g if you add 1 to an fp number, then later remove 1 from the result, you aren't guaranteed to be back at the original value. You may be a little more or less as the intermediate result may not be representable as a float.
My favorite example: .1f + .2f > .3f
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With