2
\$\begingroup\$

I am making a bomberman clone and I'm having problems regarding moving on both x and y axis (pressing down+left, down+right, up+left). Here is a video to demonstrate the problem. I use Tiled for the map. Below is the code:

private void checkCollision(float delta) {
    player.getVelocity().scl(delta); // dont mind
    Vector2 position = player.getPosition();

    if(player.isMovingRight()) {
        Array<Rectangle> tiles = getTiles((int)(position.x/TILE_SIZE + 1), (int)(position.y/TILE_SIZE - 1), 
                (int)(position.x/TILE_SIZE + 1), (int)(position.y/TILE_SIZE + 1));
        for (Rectangle tile : tiles) {
            if(player.getRectangle().overlaps(tile)) {
                System.out.println("overlap right");
                player.setPosition(tile.x - player.getWidth() , player.getPosition().y);
            }
        }
    }
    if(player.isMovingLeft()) {
        Array<Rectangle> tiles = getTiles((int)(position.x/TILE_SIZE - 1), (int)(position.y/TILE_SIZE - 1), 
                (int)(position.x/TILE_SIZE + 1),  (int)(position.y/TILE_SIZE + 1));
        for (Rectangle tile : tiles) {
            if(player.getRectangle().overlaps(tile)) {
                System.out.println("overlap left");
                player.setPosition(tile.x + tile.width, player.getPosition().y);
            }
        }
    }

    if(player.isMovingUp()) {
        Array<Rectangle> tiles = getTiles((int)(position.x/TILE_SIZE - 1), (int)(position.y/TILE_SIZE - 1), 
                (int)(position.x/TILE_SIZE + 1), (int)(position.y/TILE_SIZE));
        for (Rectangle tile : tiles) {
            if(player.getRectangle().overlaps(tile)) {
                System.out.println("overlap up");
                player.setPosition(player.getPosition().x, tile.y + tile.height);
            }
        }
    }
    if(player.isMovingDown()) {
        Array<Rectangle> tiles = getTiles((int)(position.x/TILE_SIZE - 1), (int)(position.y/TILE_SIZE + 1), 
                (int)(position.x/TILE_SIZE + 1), (int)(position.y/TILE_SIZE + 1));
        for (Rectangle tile : tiles) {
            if(player.getRectangle().overlaps(tile)) {
                System.out.println("overlap down");
                player.setPosition(player.getPosition().x, tile.y - player.getHeight());
            }
        }
    }

    player.getVelocity().scl(1/delta);

}

private Array<Rectangle> getTiles(int startX, int startY, int endX, int endY) {
    TiledMapTileLayer layer = (TiledMapTileLayer)level.getMap().getLayers().get(1);
    Array<Rectangle> rectangles = new Array<Rectangle>();
    for (int x = startX; x <= endX; x++) {
        for (int y = startY; y <= endY; y++) {
            Cell cell = layer.getCell(x, y);
            if(cell != null) {
                Rectangle rect = new Rectangle(x*TILE_SIZE, y*TILE_SIZE, TILE_SIZE, TILE_SIZE);
                rectangles.add(rect);
            }
        }
    }
    return rectangles;
}

To reproduce the problem shown in the video: Try to collide (coming from up) with one of the blocks that is not on the sides, press both down and left. Try again but press down and right. For the third one, make sure you are colliding with the top wall by pressing up then press left (both are pressed). It can also be done on the bottom wall by pressing down and left.

\$\endgroup\$
2
  • \$\begingroup\$ specific steps to reproduce it? \$\endgroup\$ Commented Jan 11, 2016 at 10:01
  • \$\begingroup\$ i'm surprised you seem to re-locate the player at x-/+tileWidth or y-/+tileHeight except for the right where you relocate at x-playerWidth. Could you show what prints when there's the bug ? \$\endgroup\$ Commented Jan 12, 2016 at 7:07

1 Answer 1

1
\$\begingroup\$

This is almost a comment, but too long so i'll post as an answer. Hopefully it will help.

There's a design flaw i think in your code : you solve on x then on y but in both cases you set both x and y...
So when you solve on Y, you 'break' the solve on X you just made.

I think you should split the collision detection and its resolution :

(pseudo-code)

 var alignOnX = false, alignOnXCoordinates = -1;
 var alignOnY = false, alignOnYCoordinates = -1;

 // detection

 if (moving left && collide left) 
     alignOnX = true;
     alignOnXCoordinates = the right coord

 if (moving right && collide right ) 
     alignOnX = true;
     alignOnXCoordinates = the right coord

 if (moving up && collide up ) 
     alignOnY = true;
     alignOnYCoordinates = the right coord

 if (moving down && collide down ) 
     alignOnY = true;
     alignOnYCoordinates = the right coord

  // resolution

  if (!alignOnX && !alignOnY) return; // regular move, just return

  var newX = expectedX, newY = expectedY;

  if (alignOnX) newX = alignOnXCoordinates;
  if (alignOnY) newY = alignOnYCoordinates;

  setCoords(newX, newY) 
\$\endgroup\$
1
  • \$\begingroup\$ I tried this and it's still the same. \$\endgroup\$
    – Zik
    Commented Jan 12, 2016 at 3:54

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .