0
\$\begingroup\$

When I move, I grab the tile in front of the player, but when the player is colliding between two tiles, I grab the wrong tile due to rounding error. I made a video explaining what I mean.

As you can see, when the player is moving down on the edge of a tile, they pass through. This is how I find the tile:

Tile t = world.tiles[(int) ((int) getX() / 32 + x)][(int) ((int) getY() / 32 + y)];`

This is 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 in the AABB class is the center of the entity and the size is half the size of the player.

How can I fix this so it finds the correct tile?

Edit: Ok, I changed my move method to get the tiles around the player, but now the player only collides if he is colliding in the middle of four solid tiles! I don't understand!

private void move(int x, int y, float sx, float sy) {
    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);
    if (getX() / 32 + x > 0 && getX() / 32 + x < world.mx && getY() / 32 + y > 0 && getY() / 32 + y < world.my) {

        for (int xx = 0; xx <= 1; xx++) {
            for (int yy = 0; yy <= 1; yy++) {
                if (world.getTile((int) (getX() / 32) + xx, (int) (getY() / 32) + yy) != null) {
                    Tile t = world.getTile((int) (getX() / 32) + xx, (int) (getY() / 32) + yy);
                    t.color = true;
                    if (t.type != 0 && !Collision.isColliding(box, t.getBox())) {
                        setPos(getX() + sx, getY() + sy);
                    } else if (t.type == 0) {
                        setPos(getX() + sx, getY() + sy);
                    }
                } else {
                    setPos(getX() + sx, getY() + sy);
                }
            }
        }

    } else {
        setPos(getX() + sx, getY() + sy);
    }
    glPushMatrix();
    glTranslatef(getX(), getY(), 0);
    glPopMatrix();
}

The type in Tile is just for checking to see if the tile is air. As you can see, I have two for loops that loop through the four tiles above, below and to the right and left of the player, and see if he collides with any of them. I have no idea why this isn't working, and I've tried to figure out how to do this for a week now. Can anyone show me a link or code to get the tiles around a player and see if he collides with them?

\$\endgroup\$
2
  • 2
    \$\begingroup\$ I am not sure it's a rounding error. If I get your code correctly, you are just considering left corner of player when 'grabbing' the tile. You should check for both left and right corners, in order to work properly. But if I got your problem wrong, a little more code explanation would help. What are 'x' and 'y' exactly? \$\endgroup\$ Commented Dec 11, 2013 at 16:07
  • \$\begingroup\$ x and y are the tile based movements. For instance, if I want to move up, I call my move method with an x value of 0 and a y value of 1. I realize its not a rounding error, more that its just since my tiles are in an array, the wrong tiles are being picked. \$\endgroup\$
    – user20439
    Commented Dec 11, 2013 at 17:08

1 Answer 1

1
\$\begingroup\$

The comments have it covered pretty well, but just to lay it out there:

Your current code is treating your tile as though it's a point. The most common case for your tile, however, is that it's overlapping two tile boundaries (whether horizontally or vertically) because of its size (again, horizontally or vertically).

Change your above code to a loop that checks tileX and tileX + 1; and tileY and tileY + 1; and you should be good to go.

\$\endgroup\$
2
  • \$\begingroup\$ Actually, why would I need a loop? Can I not just grab the tiles without one? \$\endgroup\$
    – user20439
    Commented Dec 11, 2013 at 23:07
  • \$\begingroup\$ Yeah, you're right: you could just grab tile1, tile2, tile3, tile4 and check those. Just trying to cover the case where you're placing something bigger than a single tile. \$\endgroup\$
    – drhayes
    Commented Dec 13, 2013 at 1:41

You must log in to answer this question.