0
\$\begingroup\$

I am trying to make a bomberman clone. I'm having problems with the collision on the walls that is not on the sides of the map (see image). When I come from the right (going left), the red square (player) goes through the wall but when I come from other sides (up, left, down) the collision works well and the player does not go through. The collision on the side walls works well also even when I come from the right and going left. enter image description here

I am using Tiled and LibGDX and here is the code:

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

    // just to see if it overlaps because this is the location of the 
    // rectangle when getTiles is called when player moves left as shown in the image
    Rectangle rect = new Rectangle(128, 128, 64, 64);  
    if(player.getRectangle().overlaps(rect)) {
        System.err.println("overlap"); 
    }

    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"); // this doesn't show
                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;
}
\$\endgroup\$
  • 1
    \$\begingroup\$ What does the isMovingLeft method look like? Also, why are you creating a new playerRect in each if-statement if the player already has a getRectangle method? \$\endgroup\$ – bornander Jan 7 '16 at 8:28
  • \$\begingroup\$ i don't know libGDX so tell me what is your Reference/Anchor/Pivot point when you are creating Player Rect? Means (int)position.x and (int)position.y represents what point, center? or upper left corner? \$\endgroup\$ – Hamza Hasan Jan 7 '16 at 8:34
  • \$\begingroup\$ @bordander sorry, I forgot to change it back to player.getRectangle(). \$\endgroup\$ – Zik Jan 7 '16 at 8:47
  • \$\begingroup\$ @Hamza Hasan it's in the upper left \$\endgroup\$ – Zik Jan 7 '16 at 8:47
  • \$\begingroup\$ In player.isMovingLeft() check, try to change 3rd parameter of getTiles from (int)(position.x/TILE_SIZE - 1) to (int)(position.x/TILE_SIZE + 1) \$\endgroup\$ – Hamza Hasan Jan 7 '16 at 8:55
2
\$\begingroup\$

The glitch is in your isMovingLeft method. You are giving in getTiles same X value in start and end. That is why it is creating no geometrical area.

So change do change in player.isMovingLeft() check, 3rd parameter of getTiles from (int)(position.x/TILE_SIZE - 1) to (int)(position.x/TILE_SIZE + 1).

By this it will create an area of your tile size.

\$\endgroup\$
  • \$\begingroup\$ But in the getTiles method, my for loop condition is <= so it should still make at least 1 area \$\endgroup\$ – Zik Jan 7 '16 at 10:40
  • \$\begingroup\$ @Zik what about your boundaries? are they also considered as tiles? \$\endgroup\$ – Hamza Hasan Jan 7 '16 at 11:07
  • \$\begingroup\$ Do you mean the walls on the sides? Yes, and they are part of the collision checking \$\endgroup\$ – Zik Jan 7 '16 at 13:11
  • \$\begingroup\$ And with -1 it is colliding with walls? if so then don't you thing that your once called for loop considering that wall? \$\endgroup\$ – Hamza Hasan Jan 7 '16 at 13:12
  • \$\begingroup\$ Yes, the player collides with the walls. Anyway, after this problem was solved, I have another problem and I might put it into another question. \$\endgroup\$ – Zik Jan 7 '16 at 13:15
0
\$\begingroup\$
  1. Check if there is a collision.
  2. Find the direction of the collision.
  3. Move the player to the opposite side.

Forget about checking which direction the player is moving. get rid of if(player.isMovingLeft()) and others.

After finding collision, compare the positions of the tile and the player to find the direction of the collision. Then move player in the other direction. If you are using speed*timeElapsed to move the player normally, use it again when moving in the other direction from the collision.

In order to find the direction of the collision:

if (player.width/2 + tile.width/2 < Math.abs(player.x - tile.x)) {  
    // collsion  from left or right
    if (player.x > tile.x) {
        player.setPosition(tile.x + player.width/2 + tile.width/2, player.y)
    }
    else {
        player.setPosition(tile.x - player.width/2 - tile.width/2, player.y)
    }
}

You can use this to find if there is a collision too.

NOTE: Always move player in the opposite side or reposition the pleyer, don't block movement.

\$\endgroup\$

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.