Search code examples
javacollision-detectiontile

Java Tile Game - Collision Detection


I am making a java game using tiles. I am having trouble with the collision element. I am defining rectangles for each tile on the map, and another rectangle for the player. What I am having trouble with is knowing which side the player is coming from when it hits the rectangle, and then pushing the player off in the direction the player came from. I have already made a method that checks how much the character is inside the rectangle, so it can know how much to push it out, but I can't figure out how to tell which side the character is coming from.

here is my current collision methoe - note rect1 is the character and rect2 is the tile

public void collision(Rectangle rect1, Rectangle rect2) {
    float xAdd;
    float xAdd2;
    float yAdd;
    float yAdd2;

    boolean hitRight = false;
    boolean hitLeft = false;
    boolean hitTop = false;
    boolean hitBot = false;

    Vector2f rect1Origin = new Vector2f(rect1.x, rect1.y);
    Vector2f rect2Origin = new Vector2f(rect2.x, rect2.y);
    Vector2f rect1Mid = new Vector2f((rect1.x + rect1.width) / 2,(rect1.y + rect1.height) / 2);
    Vector2f rect2Mid = new Vector2f((rect2.x + rect2.width) / 2,(rect2.y + rect2.height) / 2);

    Vector2f rect1A = new Vector2f(rect1Origin.x + rect1.width, rect1.y);
    Vector2f rect1B = new Vector2f(rect1Origin.x, rect1Origin.y+ rect1.height);
    Vector2f rect1C = new Vector2f(rect1Origin.x + rect1.width,rect1Origin.y + rect1.height);

    Vector2f rect2A = new Vector2f(rect2Origin.x + rect2.width, rect2.y);
    Vector2f rect2B = new Vector2f(rect2Origin.x, rect2Origin.y
            + rect2.height);
    Vector2f rect2C = new Vector2f(rect2Origin.x + rect2.width,
            rect2Origin.y + rect2.height);

    xAdd = rect2C.x - rect1B.x;
    xAdd2 = rect1C.x - rect2B.x;

    yAdd = rect2A.y - rect1B.y;
    yAdd2 = rect2C.y - rect1A.y;


    if (rect1Mid.y < rect2Mid.y) {
        if (rect1.intersects(rect2)) {
            y_pos += yAdd;
        }
    }
    if (rect1Mid.y > rect2Mid.y) {
        if (rect1.intersects(rect2)) {
            System.out.println(yAdd2);
            y_pos += yAdd2;
        }

    }
    if(rect1Mid.x > rect2Mid.x){
        if(rect1.intersects(rect2)){
            hitRight = true; x_pos += xAdd;
        }
    } 
    if(rect1Mid.x< rect2Mid.x){ 
          if(rect1.intersects(rect2)) {
              x_pos += -xAdd2;
          } 
    }
}

Any help would be greatly appreciated

Thanks


Solution

  • Keep two positions for your character - where the it is (as of last frame, move, etc.), and where you want to move it. Then only move it if you don't detect collision - if you don't allow for corrupt state, you don't have to fix it.

    Edit: The collision method should be boolean - it should be done before actually moving the character, like

    if (!collision(character, tile))
    {
        doMove(character);
    }
    else
    {
        //custom handling if required
    }
    

    Edit2: The previous would work only for a small step, if you need a partial move, you really need to know the character's original position, like move(originalPosition, desiredPosition, tile), where you can deduce the direction from the originalPosition and the tile.

    The main point is, you don't actually move the character, before you have a valid position for it.