繁体   English   中英

基于图块的碰撞检测,物体掉落到图块中

[英]Tile based collision detection, object falls through tiles

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

我发现角色移动得太快了。 我已经添加了一些东西来检查角色是否已经传递了任何切片,请参见注释中的“ // 1”到“ // 1 end”。 我认为这真的没有帮助,因为问题仍然存在。

尽管我不确定,但当角色碰到瓷砖的角落时,似乎会掉落瓷砖。 它不会在平坦的地面上发生。 这是问题的图片(左边是错误的,右边是应该的样子):

在此处输入图片说明

同样,该问题仅在较低的帧率下发生。 我不确定我必须在代码中进行哪些更改。 我的代码中缺少什么? 还是我必须使用其他算法?

这是冲突检测代码中最重要的部分。 碰撞Y检查y轴上的碰撞,碰撞X检查x轴上的碰撞。 CheckTiles(checkX)帮助查找应检查的图块(如果选中了x轴,则选中了true,如果选中了y轴,则checkX为true):

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};
}

只有在A) rect.overlaps(tile)true且B) velocity.y > 0false true ,才会运行“检查上方的图块”代码。 我怀疑在您关心的情况下,此代码根本没有被执行。 角色不是与图块重叠,因此不会对上方的图块进行检查,或者角色的速度不会使检查发生。 但是,我不完全了解速度的工作原理(上下如何对应正值和负值?),我对这个游戏引擎并不熟悉。

不过,我会尝试另一种方法。 与其先移动角色(我认为这是rect.y += velocity.y;所做的rect.y += velocity.y; ),然后尝试检查它是否走得太远或穿过瓷砖,我不如选择一个方向它正在移动( velocity.y ),并寻找它将以这种方式撞击第一个图块 如果有一个,则将角色放在该图块上。 如果在该方向上没有velocity.y单位的方式,则它将在此时间段内移动整个距离。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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