java swing - 如何确定两个矩形之间碰撞的一面

时间:2014-11-06 14:28:11

标签: java swing collision-detection collision

我正在使用java swing构建一个自上而下的2D滚动条,其游戏玩法与经典游戏Bomberman非常相似,玩家可以在所有4个主要方向上移动角色。

所有游戏对象都有实例变量,包含它们在JPanel上渲染的位置的(x,y)坐标,它们还有前一个(x,y)坐标的实例变量,它们在最后一个中呈现帧。我的碰撞检测算法基本上检查每次刷新屏幕时玩家对象是否与网格中存在的一个墙相交 - 这可以在下面的代码中看到:

if (playerRectangle.intersects(wallRectangle)) {
  player.restorePreviousPosition();
}

restorePreviousPosition()方法将播放器的(x,y)坐标设置为碰撞发生前的坐标。这种方法工作正常,它可以防止玩家通过对象。然而,控件似乎非常锯齿状,因为如果玩家在与墙壁接触时试图向左和向上移动,则角色保持静止。换句话说,角色不能触及墙壁并仍然平行于墙壁移动。为了解决这个问题,我创建了四个在玩家对象顶部绘制的矩形,用于确定与另一个对象碰撞的一侧,这样我可以恢复x或y,而不是恢复(x,y)坐标。在哪一方碰撞。例如,如果我知道顶部与某些东西发生碰撞,那么我可以恢复y位置并允许x自由变化。下面你可以看到播放器对象的图片,上面画着矩形:

enter image description here

这个想法非常不可靠,特别是在角落里很难确定碰撞来自哪一侧。所以,我的问题是,如何使用swing可靠地确定矩形的哪一侧与java中的另一个矩形相撞?或者,您是否有更好的替代方法来检测碰撞?

请注意,玩家移动是完全免费的,我的实现不会将角色从拼贴到拼贴。并且瓷砖之间的距离为32x32像素,播放器为30x30像素。

感谢您的帮助。如果您对我的实施有任何其他疑问,请告诉我。

3 个答案:

答案 0 :(得分:1)

rects.stream().forEach((re) ->
{
    double w = 0.5 * (re.width + player.width);
    double h = 0.5 * (re.height + player.height);
    double dx = re.getCenterX() - player.getCenterX();
    double dy = re.getCenterY() - player.getCenterY();

    if (abs(dx) < w && abs(dy) < h)//collision
    {
        double wy = w * dy;
        double hx = h * dx;
        if (wy >= hx)
            if (wy >= -hx)//top of block
                player.y = re.y - player.height;//align edges
            else//right of block
                player.x = re.x + re.width;//align edges
        else
            if (wy >= -hx)//left of block
                player.x = re.x - player.width;//align edges
            else//bottom of block
                player.y = re.y + re.height;//align edges
    }
});

这将找到被击中的那一侧,并更正玩家的位置以使其与该侧的边缘对齐。我在游戏中使用了稍微复杂一些的代码,但是想法是一样的。 (在您以更新方法重新定位播放器之后执行此操作。)

答案 1 :(得分:0)

有点简单,在某个矩形A到B的右下角发生碰撞,你想知道B是否从右边碰到了A,或者从底部碰到了更多。你所要做的就是测量B的前y坐标在A的最低y坐标之上的像素数,并测量B左边x坐标的多少像素是在A&#39;的左边。最右边的x坐标。

如果x坐标与y坐标之间的差异更大,那么它就是来自底部的碰撞,否则它就是来自侧面的碰撞。

答案 2 :(得分:0)

一个非常简单的解决方案(根据您已编写的内容)是将Test-and-Move的代码拆分为两个检查。

//update.player.x.position
if (playerRectangle.intersects(wallRectangle)) {
  player.restorePreviousPosition();
}

//update.player.y.position
if (playerRectangle.intersects(wallRectangle)) {
  player.restorePreviousPosition();
}