2014-05-05 89 views
0

我的平臺遊戲進程中有一組方法用於檢測和解決實體與平鋪地圖之間的碰撞,但他們做的不好。在基於平鋪的平臺遊戲中碰撞檢測

底部的方法是一個被稱爲,例如:

player.velocity = player.velocity.add(getFinalCollisionVector()); 

其中player.velocity是Vec2D。

private List<Rectangle2D> getCollidingTiles(){ 
    List<Rectangle2D> collidingTiles = new ArrayList<Rectangle2D>(); 
    for(int x = (int) (this.getX()/Tile.SIZE); x <= (int) (this.getX()/Tile.SIZE) + this.getRect2D().getWidth()/Tile.SIZE; x++){ 
     for(int y = (int) (this.getX()/Tile.SIZE); y <= (int) (this.getX()/Tile.SIZE) + this.getRect2D().getHeight()/Tile.SIZE; y++){ 

      if(map.getTileAt(x, y).getAttribute(Attribute.SOLID)) 
       if(map.getCollisionBoxAt(x,y).isColliding(this.collisionBox)) 
        collidingTiles.add(new Rectangle2D.Double(x, y, Tile.SIZE, Tile.SIZE)); 
     } 
    }  

    return collidingTiles; 
} 
private List<Vec2D> getAllTileCollisionVectors(){ 
    List<Rectangle2D> collidingTiles = getCollidingTiles(); 
    List<Vec2D> collisionVectors = new ArrayList<Vec2D>(); 
    for(Rectangle2D rec : collidingTiles){ 
     collisionVectors.add(getCorrectionVector(rec)); 
    } 
    return collisionVectors; 
} 
private Vec2D getCorrectionVector(Rectangle2D target) 
{ 
    Vec2D ret = new Vec2D(); 

    double x1 = (this.getX() + this.getSize().x) - target.getX(); 
    double x2 = this.getX() - (target.getX() + target.getWidth()); 
    double y1 = (this.getY() + this.getSize().y) - target.getY(); 
    double y2 = this.getY() - (target.getY() + target.getHeight()); 
    // calculate displacement along X-axis 
    if (x1 < x2) 
    { 
     ret.x = x1; 
    } 
    else if (x1 > x2) 
    { 
     ret.x = x2; 
    } 
    // calculate displacement along Y-axis 
    if (y1 < y2) 
    { 
     ret.y = y1; 
    } 
    else if (y1 > y2) 
    { 
     ret.y = y2; 
    } 
    return ret; 
} 
protected Vec2D getFinalCollisionVector(){ 
    List<Vec2D> collisionVectors = getAllTileCollisionVectors(); 
    if(collisionVectors.size() < 1) 
     return new Vec2D(0,0); 

    Vec2D finalVector = new Vec2D(); 
    for(Vec2D vec : collisionVectors){ 
     finalVector = finalVector.add(vec); 
    }  
    return finalVector; 
} 

我在做什麼錯在我的代碼?這是玩家表現的行爲,他跌倒在那裏(由於重力)到那一點,然後他凍結。 The character is stuck

+0

你讀過http://stackoverflow.com/questions/13825515/java-rectangle-collision-detection-confusion? – user1803551

回答

0

OP在這裏: 由於沒有其他答案,我已經張貼我自己的。

我已經放棄了舊的實施,從頭開始,現在它的工作。這是新的實現:

public Corners getCornersAreSolid(double x, double y) { 
    int leftTile = (int)(x/Tile.SIZE); 
    int rightTile = (int)((x + moveData.collisionBox.getWidth())/Tile.SIZE); 
    int topTile = (int)(y/Tile.SIZE); 
    int bottomTile = (int)((y + moveData.collisionBox.getHeight())/Tile.SIZE); 

    boolean topLeft = hasAttribute(map, Attribute.SOLID, topTile, leftTile); 
    boolean topRight = hasAttribute(map, Attribute.SOLID, topTile, rightTile); 
    boolean bottomLeft = hasAttribute(map, Attribute.SOLID, bottomTile, leftTile); 
    boolean bottomRight = hasAttribute(map, Attribute.SOLID, bottomTile, rightTile); 

    Corners solidCorners = new Corners(); 
    solidCorners.topLeft = topLeft; 
    solidCorners.topRight = topRight; 
    solidCorners.bottomRight = bottomRight; 
    solidCorners.bottomLeft = bottomLeft; 
    return solidCorners; 
} 
private boolean hasAttribute(GameMap map, Attribute attribute, int tileY, int tileX) { 
     boolean result = false; 

     if (tileX >= 0 && tileX < map.getWidthInTiles() && tileY >= 0 && tileY < map.getHeightInTiles()) { 
     result = map.getTileAt(tileX, tileY).getAttribute(attribute); 
     } 
     return result; 
    } 
public Vec2D getNextPosition() { 

    int currCol = (int) (getX()/Tile.SIZE); 
    int currRow = (int) (getY()/Tile.SIZE); 

    double destX = getX() + moveData.velocity.x; 
    double destY = getY() + moveData.velocity.y; 

    double tempX = getX(); 
    double tempY = getY(); 

    Corners solidCorners = getCornersAreSolid(getX(), destY); 
    boolean topLeft = solidCorners.topLeft; 
    boolean topRight = solidCorners.topRight; 
    boolean bottomLeft = solidCorners.bottomLeft; 
    boolean bottomRight = solidCorners.bottomRight; 

    this.framesSinceLastCollision += 1; 
    if(moveData.velocity.y < 0) { 
     if(topLeft || topRight) { 
      moveData.velocity.y = 0; 
      tempY = currRow * Tile.SIZE; 
      this.framesSinceLastCollision = 0; 
     } 
     else { 
      tempY += moveData.velocity.y; 
     } 
    } 
    else if(moveData.velocity.y > 0) { 
     if(bottomLeft || bottomRight) { 
      moveData.velocity.y = 0; 
      tempY = (currRow + 1) * Tile.SIZE - moveData.collisionBox.getHeight() % Tile.SIZE - 1 ; 
      this.framesSinceLastCollision = 0; 
     } 
     else { 
      tempY += moveData.velocity.y; 
     } 
    } 

    solidCorners = getCornersAreSolid(destX, getY()); 
    topLeft = solidCorners.topLeft; 
    topRight = solidCorners.topRight; 
    bottomLeft = solidCorners.bottomLeft; 
    bottomRight = solidCorners.bottomRight; 
    if(moveData.velocity.x < 0) { 
     if(topLeft || bottomLeft) { 
      moveData.velocity.x = 0; 
      tempX = currCol * Tile.SIZE; 
      this.framesSinceLastCollision = 0; 
     } 
     else { 
      tempX += moveData.velocity.x; 
     } 
    } 
    if(moveData.velocity.x > 0) { 
     if(topRight || bottomRight) { 
      moveData.velocity.x = 0; 
      tempX = (currCol + 1) * Tile.SIZE - moveData.collisionBox.getWidth() % Tile.SIZE -1 ; 
      this.framesSinceLastCollision = 0; 
     } 
     else { 
      tempX += moveData.velocity.x; 
     } 
    } 
    return new Vec2D(tempX, tempY); 
} 
private static class Corners{ 
    public boolean topLeft, topRight; 
    public boolean bottomLeft, bottomRight; 
    public Corners(){ 
     topLeft = false; 
     topRight = false; 
     bottomLeft = false; 
     bottomRight = false; 
    }  
}