基于平铺的碰撞检测,物体通过瓷砖落下

时间:2014-02-07 17:35:53

标签: java libgdx collision-detection game-physics frame-rate

我在较低帧率的基于图块的级别上遇到碰撞检测问题。我有一个用Java构建的平台游戏和LibGdx游戏引擎。在60的帧速率下,游戏运行良好,但是如果我尝试30 FPS,当角色从跳跃状态下降时,角色将会掉落。

我发现角色移动得太快了。我已经添加了一些内容来检查角色是否已经传递过任何切片,请在评论中看到“// 1”到“// 1 end”。我不认为这确实有帮助,因为问题仍然存在。

当角色碰到瓷砖的角落时,似乎会发生掉落在瓷砖上,虽然我不确定。它不会发生在平坦的地面上。这是一个问题的图片(左边是错的,它应该是怎么回事):

enter image description here

同样,问题只发生在较低的帧速率下。我不确定我的代码中需要更改什么。我的代码中缺少什么?或者我必须使用不同的算法吗?

以下是碰撞检测代码中最重要的部分。 collisionY检查y轴上的碰撞,x轴上的collisionX。 CheckTiles(checkX)有助于找到应该检查的切片(如果选中了x轴,则checkX为真,如果选中了错误的y轴):

protected boolean collisionY(Rectangle rect) {
    int[] bounds = checkTiles(false);
    Array<Rectangle> tiles = world.getTiles(bounds[0], bounds[1], bounds[2], bounds[3]);
    rect.y += velocity.y;
    if(velocity.y < 0 ) {
        grounded = false;
    }
    for (Rectangle tile : tiles) {
        if (rect.overlaps(tile)) {
            if (velocity.y > 0) {
                this.setY(tile.y - this.getHeight());
            }
            else {
                // 1 Check if there are tiles above
                Rectangle r = null;
                int i = 1;
                Rectangle r1 = null;
                do {
                    r1 = r;
                    r = world.getTile(tile.x, tile.y + i);
                    i++;
                } while (r != null);
                if(r1 != null) {
                    this.setY(r1.y + r1.height);
                }
                // 1 end
                else {
                    this.setY(tile.y + tile.height);
                }
                hitGround();
            }
            return true;
        }
    }
}

protected boolean collisionX(Rectangle rect) {
    int[] bounds = checkTiles(true);
    Array<Rectangle> tiles = world.getTiles(bounds[0], bounds[1], bounds[2], bounds[3]);
    rect.x += velocity.x;
    for (Rectangle tile : tiles) {
        if (rect.overlaps(tile)) {
            return true;
        }
    }
    return false;
}


protected int[] checkTiles(boolean checkX) {
    int startX, startY, endX, endY;
    if(checkX) {
        if (velocity.x > 0) {
            startX = endX = (int) (this.getX() + this.getWidth() + velocity.x);
        }
        else {
            startX = endX = (int) (this.getX() + velocity.x);
        }
        startY = (int) (this.getY());
        endY = (int) (this.getY() + this.getHeight());
    }
    else {
        if (velocity.y > 0) {
            startY = endY = (int) (this.getY() + this.getHeight() + velocity.y); //
        }
        else {
            startY = endY = (int) (this.getY() + velocity.y);
        }
        startX = (int) (this.getX());
        endX = (int) (this.getX() + this.getWidth());
    }
    return new int[]{startX, startY, endX, endY};
}

1 个答案:

答案 0 :(得分:2)

仅当A)rect.overlaps(tile)true且B)velocity.y > 0false时,才会运行“检查上方是否为瓷砖”代码。我怀疑在你关心的情况下,这段代码根本没有被执行。字符要么不与图块重叠,所以不会检查上面的图块,或者它的速度不会发生检查。但是,我不完全理解速度是如何工作的(上下如何对应于正值和负值?)并且我不熟悉这个游戏引擎。

但是,我会尝试不同的方法。而不是先移动角色(这就是我认为线rect.y += velocity.y;所做的那样),然后尝试检查它是否已经走得太远或通过一个瓦片,我会采取它移动的方向({ {1}})并查找它会以那种方式点击的第一个图块。如果有,则将该字符放在该图块上。如果在该方向上velocity.y单位没有任何方法,那么它将在此时间片中移动整个距离。