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

问题描述 投票:3回答:3

我正在使用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自由变化。下面你可以看到播放器对象的图片,上面画着矩形:

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

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

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

java swing collision-detection collision
3个回答
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
    }
});

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


0
投票

有点简单,在一个矩形A到B的右下角发生碰撞,你想知道B是否从右边碰到了A,或者从底部碰到了更多。您所要做的就是测量B的顶部y坐标高于A的最低y坐标的像素数,并测量B的最左侧x坐标位于A的最右侧x坐标左侧的像素数。

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


0
投票

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

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

//update.player.y.position
if (playerRectangle.intersects(wallRectangle)) {
  player.restorePreviousPosition();
}
© www.soinside.com 2019 - 2024. All rights reserved.