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\$ Jan 11 '16 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\$ Jan 12 '16 at 7:07
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
    Jan 12 '16 at 3:54

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.