Java - 碰撞检测(故障)

Fee*_*man 8 java collision-detection

我正在为HS的最后一年项目制作平台游戏.然而......我使用的碰撞检测系统基本上是关于检查字符的特定部分是否与另一个块相交.

碰撞似乎工作得很好,除了它会导致一些错误,例如玩家在从侧面撞击时卡住或减速或在使用上键和<或>键时被抛出.

我的问题是; 如何改进碰撞代码以避免这种故障并发生"滑溜"碰撞?

这是我想要实现的那种碰撞效果:
(https://i.imgur.com/KB1M3bt.mp4)
在此输入图像描述

(https://i.imgur.com/I44fmPc.mp4) 在此输入图像描述

这里是边界看起来的预览

在此输入图像描述


这里是游戏中实际外观的预览(点击查看更好的质量) 在此输入图像描述
我用于碰撞检测的代码:(tempObject是玩家与之交叉的块)

if(getBoundsTop().intersects(tempObject.getBoundsBottom())){
    y = tempObject.getY() + height;
    velY = 0;
    System.out.println("Top collision");
}

if(getBoundsBottom().intersects(tempObject.getBoundsTop())){
    y = tempObject.getY() - height;
    velY = 0;
    falling = false;
    jumping = false;
    //isOnBlock = true;
} else {
    falling = true;
    //isOnBlock = false;
}

if(getBoundsRight().intersects(tempObject.getBoundsLeft())){
    x = tempObject.getX() - this.width;
}


if(getBoundsLeft().intersects(tempObject.getBoundsRight())){
    x = tempObject.getX() + this.width;
}
Run Code Online (Sandbox Code Playgroud)

这是绑定的方法:

public Rectangle getBounds() { return new Rectangle( (int)x, (int)y, (int)width, (int)height ); }

    public Rectangle getBoundsTop() {
        return new Rectangle(
                (int)x, 
                (int)y, 
                (int)(width-(width*0.01f)), 
                (int)(height/2)
        );
    }
    public Rectangle getBoundsBottom() {
        return new Rectangle(
                (int)x,
                (int)(y+(height/2)),
                (int)(width-(width*0.01f)),
                (int)(height/2)
        );
    }

    public Rectangle getBoundsLeft() {
        return new Rectangle(
                (int)x,
                (int)y, 
                (int)((int)width*0.15f), 
                (int)height
        );
    }

    public Rectangle getBoundsRight() {
        return new Rectangle(
                (int) 
                ((int)x+(width-(width*0.15f))), 
                (int)y, 
                (int) ((int)width*0.15f), 
                (int)height
        );
    }
Run Code Online (Sandbox Code Playgroud)

编辑:我使用恒定的加速度来设置速度

acc = 2.5f;
MAX_SPEED = 10;


if(Game.keyDownMap.containsKey(KeyEvent.VK_A)){

    setVelX(getVelX() - acc);
    if(getVelX() < -MAX_SPEED)
        setVelX(-MAX_SPEED);

} else if(Game.keyDownMap.containsKey(KeyEvent.VK_D)){

    setVelX(getVelX() + acc);
    if(getVelX() > MAX_SPEED)
        setVelX(MAX_SPEED);

}
Run Code Online (Sandbox Code Playgroud)

Tsc*_*cka 1

当发生侧向碰撞时,您需要将侧向速度设置为零。这样就只能有垂直速度,我假设将是 setVelY();

if(getBoundsRight().intersects(tempObject.getBoundsLeft())){
    x = tempObject.getX() - this.width;
    setVelX(0);
}


if(getBoundsLeft().intersects(tempObject.getBoundsRight())){
    x = tempObject.getX() + this.width;
    setVelX(0);
}
Run Code Online (Sandbox Code Playgroud)

此外,如果没有活动的碰撞状态,您还需要检查按键按下情况。您可能需要创建一个方法来设置它当前是否与您更新每个游戏标记的内容相交。

if(Game.keyDownMap.containsKey(KeyEvent.VK_A) && !isIntersectingLeft()){

    setVelX(getVelX() - acc);
    if(getVelX() < -MAX_SPEED)
        setVelX(-MAX_SPEED);

} else if(Game.keyDownMap.containsKey(KeyEvent.VK_D) && !isIntersectingRight()){

    setVelX(getVelX() + acc);
    if(getVelX() > MAX_SPEED)
        setVelX(MAX_SPEED);

}
Run Code Online (Sandbox Code Playgroud)

如果你想要一点反弹,你可以在不同的方向设置一点速度。

if(getBoundsRight().intersects(tempObject.getBoundsLeft())){
    x = tempObject.getX() - this.width;
    if(this.getVelX() > 0) {
        setVelX(10);
    }
}


if(getBoundsLeft().intersects(tempObject.getBoundsRight())){
    x = tempObject.getX() + this.width;
    if(this.getVelX() > 0) {
       setVelX(-10);
    }
}
Run Code Online (Sandbox Code Playgroud)