Java AABB碰撞-在靠墙移动时卡住

Java AABB碰撞-在靠墙移动时卡住,java,aabb,Java,Aabb,我试图实现一个简单的AABB系统,其中一个边界框从玩家的上一个位置和下一个位置获取玩家的边界框。应修改下一个边界框,以防止任何非法移动(即穿墙) 目前,我的代码在某种程度上是有效的。例如,当我只朝一个方向移动(键盘控制)时,我会停在正确的位置: 请注意,白色正方形是实际的边界框,红色边框是专有的右侧和底部坐标(因此红线进入地形内部是正确的) 当试图同时移动两个轴时,真正的问题出现了。e、 g.每当我抱着顶墙向左移动时(握住W),玩家就会以16*16的间隔(在每个瓷砖的边缘)被卡住。一旦我解决了

我试图实现一个简单的AABB系统,其中一个边界框从玩家的上一个位置和下一个位置获取玩家的边界框。应修改下一个边界框,以防止任何非法移动(即穿墙)

目前,我的代码在某种程度上是有效的。例如,当我只朝一个方向移动(键盘控制)时,我会停在正确的位置:

请注意,白色正方形是实际的边界框,红色边框是专有的右侧和底部坐标(因此红线进入地形内部是正确的)

当试图同时移动两个轴时,真正的问题出现了。e、 g.每当我抱着顶墙向左移动时(握住
W
),玩家就会以16*16的间隔(在每个瓷砖的边缘)被卡住。一旦我解决了这个问题,我将创建某种贪婪算法来对边界框进行分组,但目前地图中每个填充的瓷砖只有一个
BoundingBox
inti,j;添加(新的边界框(新的Vec2(i=x*16,j=y*16),新的Vec2(i+16,j+16))显示GIF中发生的事情可能更容易:

为每个边界框调用
collide
函数,从左上角开始,首先递增X,使用播放器的最后一个位置和最后一个框中修改的位置。以下是边界框的代码:

public class BoundingBox {
    public Vec2 min, max;

    public BoundingBox(Vec2 min, Vec2 max) {
        this.min = min;
        this.max = max;
    }

    @Override
    public BoundingBox clone() {
        return new BoundingBox(new Vec2(this.min.x, this.min.y), new Vec2(this.max.x, this.max.y));
    }
    public BoundingBox offset(Vec2 vec) {
        this.min.x += vec.x;
        this.max.x += vec.x;
        this.min.y += vec.y;
        this.max.y += vec.y;
        return this;
    }

    private boolean lineCollision(int leftA, int rightA, int leftB, int rightB) {
        return (leftA >= leftB && leftA < rightB) ||
            (rightA >= leftB && rightA < rightB);
    }

    public boolean collide(BoundingBox last, BoundingBox next) {
        boolean collided = false;

        if(lineCollision(last.min.y, last.max.y, this.min.y, this.max.y) || lineCollision(next.min.y, next.max.y, this.min.y, this.max.y)) {
            if(last.max.x <= this.min.x && next.max.x > this.min.x) { // Left -> Right
                next.offset(new Vec2(this.min.x - next.max.x, 0));
                collided = true;
            }
            if(last.min.x >= this.max.x && next.min.x < this.max.x) { // Right -> Left
                next.offset(new Vec2(this.max.x - next.min.x, 0));
                collided = true;
            }
        }
        if(lineCollision(last.min.x, last.max.x, this.min.x, this.max.x) || lineCollision(next.min.x, next.max.x, this.min.x, this.max.x)) {
            if(last.max.y <= this.min.y && next.max.y > this.min.y) { // Top -> Bottom
                next.offset(new Vec2(0, this.min.y - next.max.y));
                collided = true;
            }
            if(last.min.y >= this.max.y && next.min.y < this.max.y) { // Bottom -> Top
                next.offset(new Vec2(0, this.max.y - next.min.y));
                collided = true;
            }
        }
        return collided;
    }
}
公共类边界框{
公共Vec2最小值,最大值;
公共边界框(最小为Vec2,最大为Vec2){
this.min=min;
this.max=max;
}
@凌驾
公共边界框克隆(){
返回新的边界框(新的Vec2(this.min.x,this.min.y),新的Vec2(this.max.x,this.max.y));
}
公共边界框偏移(Vec2 vec){
此.min.x+=vec.x;
此.max.x+=vec.x;
此.min.y+=vec.y;
此.max.y+=vec.y;
归还这个;
}
私有布尔线冲突(int-leftA、int-rightA、int-leftB、int-rightB){
返回(leftA>=leftB&&leftA=leftB&&rightARight
next.offset(新的Vec2(this.min.x-next.max.x,0));
碰撞=真;
}
如果(last.min.x>=this.max.x&&next.min.xLeft
next.offset(新的Vec2(this.max.x-next.min.x,0));
碰撞=真;
}
}
if(线条碰撞(last.min.x,last.max.x,this.min.x,this.max.x)|线条碰撞(next.min.x,next.max.x,this.min.x,this.max.x)){
如果(last.max.y this.min.y){//Top->Bottom
next.offset(新的Vec2(0,this.min.y-next.max.y));
碰撞=真;
}
如果(last.min.y>=this.max.y&&next.min.yTop
next.offset(新的Vec2(0,this.max.y-next.min.y));
碰撞=真;
}
}
返回碰撞;
}
}
也许这个问题与操作顺序有关?这似乎不太可能,但如果
collide
中的
语句改变了行为,那么这两个
语句的顺序似乎发生了改变——我被卡住的墙壁也改变了

据我所知,第一次发生碰撞时,合成向量应该在墙外,所以它不再碰撞-对吗?这里一定有某种逻辑错误,但我自己无法发现


根据请求,此pastebin中提供了额外代码:

您可能希望链接到pastebin,即您需要的完整代码use@Coffee以下是相关代码的其余部分: