【问题标题】:Reflection circle / rectangle problems反射圆/矩形问题
【发布时间】:2017-08-07 08:42:17
【问题描述】:

我正在尝试重新创建突破,但块角和球之间的相互作用让我非常头疼。从窗户的边缘和积木弹起效果很好,从窗户的角落弹起也很完美。为简单起见,所有块都是轴对齐的。交换 x 和 y 运动仅适用于 8 个案例中的 2 个。对于其他 6 个,必须反转一个或两个向量才能使碰撞正确,但我无法找到一种简单的方法来做到这一点。写 8 个 if 语句是不正确的,容易引起 bug。

Ball 类是 Ellipse2D.Double 类的扩展。
Block 类是 Rectangle 类的扩展。

我查看的每个问题/答案/教程要么过于复杂(不是 AA 矩形,矩形不在固定位置上),要么是简化(就像两个矩形碰撞一样处理)或完全偏离主题(检测碰撞/重叠,球对球的处理)。

这是我得到的:

public void move(Paddle p, List<Block> b) {
    //called every frame

    this.x += dx;
    this.y += dy;

    checkCollisionsWalls();
    // checkCollisionPaddle(p);
    checkCollisionBlocks(b);

    if (this.dir == 90 || this.dir == 270)
        this.dir++;
    // make sure ball wont get stuck between two walls of window

}

private void checkCollisionBlocks(List<Block> b) {

    for (Block block : b) {

        if (this.intersects(block)) {

            if (this.x + this.width / 2 >= block.x && this.x + this.width / 2 <= block.x + block.width) {

                System.out.println("Top / Bot reflect");
                this.dy *= -1;
                break;
            }

            if (this.y + this.height / 2 >= block.y && this.y + this.height / 2 <= block.y + block.height) {
                System.out.println("Left / Right reflect");
                this.dx *= -1;
                break;
            }

            // if execution got here we must have hit a corner
            reflectCorner();

        }
    }
}

private void reflectCorner() {

    if (dx > dy) {
        this.dy *= -1;
    } else {
        this.dx *= -1;
    }

    if (Math.abs(dx) == Math.abs(dy)) {
        this.dy *= -1;
        this.dx *= -1;
    }

    double temp = this.dx;
    this.dx = this.dy;
    this.dy = temp;
    temp = 0;

}

dx 和 dy 是 Ball 类中的全局变量,实际上所有代码都(仍然)在 Ball 类中。

编辑: 很抱歉看到提出明确问题的部分,我对此有点激动...

当前代码发生了什么: 从任何方向击中右下角时​​,反射都能完美发挥作用。
击中左上角会导致球卡在矩形内。然后它沿着边缘游荡到右下角
在平行于 x 轴移动时触摸右上角以及在平行于 y 轴移动时触摸左下角时,球会反射两次,在正 y 或正 x 方向上微动,每次反弹一个像素(它移动到的正交轴)。
所有其他反射都可以正常工作。

应该发生什么: reflectCorner() 方法应该适用于所有角落,就像它适用于右下角一样,并且不会产生上述结果。

问题: 如何在不使用过于复杂的 if 结构的情况下做到这一点?

如有必要,我可以提供我使用的测试设置。

【问题讨论】:

  • 寻求调试帮助的问题(“为什么这段代码不起作用?”)必须包括所需的行为、特定的问题或错误以及在问题本身中重现它所需的最短代码。没有明确问题陈述的问题对其他读者没有用处。请参阅:如何创建 minimal reproducible example。使用“编辑”链接改进您的问题 - 不要通过 cmets 添加更多信息。谢谢!
  • 换句话说:您的问题到底是什么?

标签: java collision game-physics


【解决方案1】:

我终于设法让它在各个方面都发挥作用。首先,我通过检查球的中心和任何角落之间的距离是否小于/等于球的半径来计算击中哪个角落。然后我会交换 x 和 y 运动。对于两个角,这就是所有需要的,对于第二个,我必须反转其中一个,这取决于球的角和方向。

最后:

private void reflectCorner(Rectangle rect) {

    double temp = this.dx;
    this.dx = this.dy;
    this.dy = temp;
    temp = 0;

    if (Math.abs(dx) == Math.abs(dy)) {
        this.dy *= -1;
        this.dx *= -1;
        return;
    }

    if (Math.sqrt(Math.pow(Math.abs(this.getCenterX() - rect.x), 2)
            + Math.pow(Math.abs(this.getCenterY() - rect.y), 2)) <= this.width / 2) {
        System.out.println("topL");
        if (dx < dy) {
            this.dy *= -1;
        } else {
            this.dx *= -1;
        }
        return;
    }
        if (Math.sqrt(Math.pow(Math.abs(this.getCenterX() - (rect.x + rect.width)), 2)
           + Math.pow(Math.abs(this.getCenterY() - (rect.y + rect.height)), 2)) <= this.width / 2) {
        System.out.println("botR");
        if (dx > dy) {
            this.dy *= -1;
        } else {
            this.dx *= -1;
        }
        return;
    }

}

更多我不需要,而且它相对紧凑。不过,如果有人有更简单的想法,你仍然可以回答,我会测试它。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-11-12
    • 1970-01-01
    • 1970-01-01
    • 2021-07-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多