I implemented some basic collision detection using AABBs and it mostly works, except for the fact that when I move down towards a collidable object, the player can pass through, but only when approaching the object after moving to the left. Here’s a picture of what I mean:
If you can see, the player (the white square), is intersecting a tile. The player can only pass through a tile when there is no tiles under the player, and you are moving left and then down. Here’s my collision detection code:
public static boolean isColliding(AABB a, AABB b) {
if (Math.abs(a.pos.getX() - b.pos.getX()) < a.size + b.size) {
if (Math.abs(a.pos.getY() - b.pos.getY()) < a.size + b.size) {
return true;
}
}
return false;
}
The pos variable is actually the center of the AABB, and the size variable is half the size. Here’s how I detect a collision in the entity class:
private void move(float x, float y, float sx, float sy) {
if (getX() / 32 + x >= 0 && getX() / 32 + x <= world.mx && getY() / 32 + y >= 0 && getY() / 32 + y <= world.my) {
if (world.tiles[(int) ((int) getX() / 32 + x)][(int) ((int) getY() / 32 + y)] != null) {
Vector2f tempPos = new Vector2f((pos.getX() + (pos.getX() + 32)) / 2, (pos.getY() + (pos.getY() + 32)) / 2);
box.update(new Vector2f(tempPos.getX() + sx, tempPos.getY() + sy), 16);
Tile t = world.tiles[(int) ((int) getX() / 32 + x)][(int) ((int) getY() / 32 + y)];
t.color = true;
if (!Collision.isColliding(box, t.getBox())) {
setPos(getX() + sx, getY() + sy);
} else if (Collision.isColliding(box, t.getBox())) {
if (!onGround)
onGround = true;
}
} else {
setPos(getX() + sx, getY() + sy);
}
} else {
setPos(getX() + sx, getY() + sy);
}
glPushMatrix();
glTranslatef(getX(), getY(), 0);
glPopMatrix();
}
Specifically these lines are important:
Vector2f tempPos = new Vector2f((pos.getX() + (pos.getX() + 32)) / 2, (pos.getY() + (pos.getY() + 32)) / 2);
box.update(new Vector2f(tempPos.getX() + sx, tempPos.getY() + sy), 16);
Tile t = world.tiles[(int) ((int) getX() / 32 + x)][(int) ((int) getY() / 32 + y)];
t.color = true;
if (!Collision.isColliding(box, t.getBox())) {
setPos(getX() + sx, getY() + sy);
I construct a new Vector (tempPos) that is the center of the entity in question. Then I update the AABB with the center of the entity, and then I add either sx or sy, which is the movespeed, generally speaking this is usually set to 8, so I move 8 pixels every update, and the tiles are 32 pixels in size. Then I get the tile immediately to the wherever the player is moving using the x and y variables.
Just for reference, here is my keyboard update code for the player:
if (Keyboard.isKeyDown(Keyboard.KEY_SPACE)) {
move(0, 1, 0, MOVESPEED);
}
if (Keyboard.isKeyDown(Keyboard.KEY_D)) {
move(1, 0, MOVESPEED, 0);
}
if (Keyboard.isKeyDown(Keyboard.KEY_A)) {
move(-1, 0, -MOVESPEED, 0);
}
if (Keyboard.isKeyDown(Keyboard.KEY_LSHIFT)) {
move(0, -1, 0, -MOVESPEED);
}
if (Keyboard.isKeyDown(Keyboard.KEY_SPACE) && onGround) {
onGround = false;
vY = 4f;
}
If I change this line:
box.update(new Vector2f(tempPos.getX() + sx, tempPos.getY() + sy), 16);
To instead add the x and y variables, like this:
box.update(new Vector2f(tempPos.getX() + x, tempPos.getY() + y), 16);
Then the collision works correctly, but now it doesn’t detect collisions on the y axis at all. x and y are constrained between 1 and -1, as you can see in the keyboard update code. It’s used to look up the tile where the player wants to move, so I don’t know why only the x axis is working, and not the y.
Sorry if I didn’t explain this well enough, ask me and I’ll clarify anything!