简体   繁体   中英

java 2d platformer collision bug

When the character walks in to a wall they can't go through but when jumping in to a wall, the player is teleported up or down depending on how high you hit the tile.

How can i make so that the player just falls when they hit a wall?

The movement and collision detection happens in Player.java.

I think it has to do with checkin if the player is standing on a block (the first check in the for loop) but im not sure.

link to the files on github

a visual representation of my problem

This is how i check for collision:

public void collisionCheck(){
    for (ArrayList<Integer> tile: Game.tileCoordinates){
        //current row of the player
        int row = y / Game.TILE_SIZE;
        // the row below the player
        int rowBelow = y / Game.TILE_SIZE + 1;
        // the column the left of the player is in
        int columnLeft = x / Game.TILE_SIZE;
        // the column the right of the player is in
        int columnRight = (x + width) / Game.TILE_SIZE;

        // check if the player goes through the block below
        if (tile.get(1) / Game.TILE_SIZE == rowBelow){
            if ((tile.get(0) / Game.TILE_SIZE == columnLeft || 
                 tile.get(0) / Game.TILE_SIZE == columnRight)) {
                y = tile.get(1) - height;
                if (jumping) {
                    jumping = false;
                    Game.spacePressed = false;
                    dustAfterShowed = false;
                    xAfterJump = x;
                    yAfterJump = y;
                }
                if (falling){
                    falling = false;
                }
            }
        }

        // check if the player goes through the side of a block
        if (y <= tile.get(1) && y + height <= tile.get(1) + Game.TILE_SIZE &&
               y + height >= tile.get(1) && row == tile.get(1) / Game.TILE_SIZE) {
            // left side
            if (x + width >= tile.get(0) && x <= tile.get(0)) {
                x = tile.get(0) - width;
            }
            // right side
            if (x + width >= tile.get(0) + Game.TILE_SIZE && 
                    x <= tile.get(0) + Game.TILE_SIZE) {
                x = tile.get(0) + Game.TILE_SIZE;
            }
        }
        // check if the player hits a block from below
        if (tile.get(1) / Game.TILE_SIZE == row && 
               (tile.get(0) / Game.TILE_SIZE == columnLeft ||
                tile.get(0) / Game.TILE_SIZE == columnRight)){
            if (jumping) {
                y = tile.get(1) + Game.TILE_SIZE;
                velocity = 0;
            }
        }
    }

I fixed it by addig a few booleans, when the player hits a wall from the side, it now doesn't check for bottom tile collision anymore (making the player fall instead of stay mid air).

When checking for top tile collision, you check in advance. if you dont check in advance it will detect side collision because the top left and right pixel are in the tile.

    for (ArrayList<Integer> tile: Game.tileCoordinates){
        sideCollision = false;
        blockRight = false;
        blockLeft = false;

        // check for side collision, if colided then disable movement
        if ((y / Game.TILE_SIZE == tile.get(1) / Game.TILE_SIZE) &&
                (x < tile.get(0) && x + width > tile.get(0) &&
                 x + width < tile.get(0) + Game.TILE_SIZE)) {
            sideCollision = true;
            blockRight = true;
            x = tile.get(0) - width - 1;
        }

        if ((y / Game.TILE_SIZE == tile.get(1) / Game.TILE_SIZE) &&
                (x < tile.get(0) + Game.TILE_SIZE && x > tile.get(0) &&
                 x + width > tile.get(0) + Game.TILE_SIZE)) {
            sideCollision = true;
            blockLeft = true;
            x = tile.get(0) + Game.TILE_SIZE + 1;
        }

        // if player is about to hit head, stop upwards movement
        if ((y - velocity <= tile.get(1) + Game.TILE_SIZE &&
                 y - velocity > tile.get(1)) && ((x >= tile.get(0) &&
                 x <= tile.get(0) + Game.TILE_SIZE) ||
                (x + width >= tile.get(0) &&
                 x + width <= tile.get(0) + Game.TILE_SIZE))){
            y = tile.get(1) + Game.TILE_SIZE;
            velocity = 0;
        }

        // if there is no side collision, check for bottom collision
        if (!sideCollision) {
            if ((y / Game.TILE_SIZE + 1 == tile.get(1) / Game.TILE_SIZE) &&
                    (y + height > tile.get(1)) &&
                   ((x >= tile.get(0) && x <= tile.get(0) + Game.TILE_SIZE) ||
                    (x + width >= tile.get(0) &&
                     x + width <= tile.get(0) + Game.TILE_SIZE))) {
                y = tile.get(1) - height;
                if (jumping) {
                    jumping = false;
                    Game.spacePressed = false;
                    dustAfterShowed = false;
                    xAfterJump = x;
                    yAfterJump = y;
                }
                if (falling) {
                    falling = false;
                }
            }
        }
    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM