【问题标题】:Break Out Collision Detection爆发碰撞检测
【发布时间】:2015-03-27 12:07:41
【问题描述】:

我正在尝试一个简单的 Break Out 克隆,以了解游戏状态、游戏循环等。

我遇到的困难之一是碰撞检测。

我有一个由 Ball、Brick 和 Paddle 扩展的 GameItem 类。在这个类中,我有一个 getBounds() 方法来返回对象的边界矩形,一个碰撞(GameItem 项目)方法来确定 2 个 GameItem 对象是否发生碰撞以及 hitTop()hitBottom() 的方法, hitLeft()hitRight() 来确定对象的哪一侧与另一侧发生碰撞。

这些方法如下:

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

public boolean collision(GameItem item)
{       
    return getBounds().intersects(item.getBounds());        
}   

public boolean hitTop(GameItem item)
{       
    return getY()+getHeight()>=item.getY();     
}

public boolean hitLeft(GameItem item)
{
    return getX()+getWidth()>=item.getX();
}   

public boolean hitBottom(GameItem item)
{
    return getY()<=item.getY()+item.getHeight();
}

public boolean hitRight(GameItem item)
{
    return getX()<=item.getX()+item.getWidth();
}

ball 类有一个名为checkBallCollissions(GameItem item) 的方法来确定球何时击中另一个对象。如下:

public boolean checkBallCollisions(GameItem item)
{
    if(this.collision(item))
    {
        if(this.hitTop(item))
        {
            this.setVY(-1*this.getVY());
            return true;
        }
        else if(this.hitBottom(item))
        {
            this.setVY(-1*this.getVY());
            return true;
        }
        else if(this.hitLeft(item))
        {
            this.setVX(-1*this.getVX());
            return true;
        }
        else if(this.hitRight(item))
        {
            this.setVX(-1*this.getVX());
            return true;
        }
        return false;
    }
    return false;
}

如下调用:

ball.checkBallCollisions(paddle);

如您所见,如果它碰到 4 个边缘之一,x/y 方向会相应地反转。

但是,这不起作用。分析代码似乎有一个明显的问题,我无法理解解决方案。

下面的 3 张图片显示了球与物体从上方、下方和右侧的碰撞。

按照现在的代码,它首先根据边界矩形和 intersects() 方法检测碰撞。然后它确定它击中了哪一侧。如果它从上面击中它就可以工作。但是,当它从底部或右侧击中时,hitTop() 将返回 true,因为 getY()+getHeight()&gt;=item.getY() 在这两种情况下都为 true(即球的底部边缘的 y 值大于与它碰撞的对象的顶部边缘)。

我缺少什么条件来解决这个问题并进行完美的碰撞检测?

【问题讨论】:

标签: java swing awt collision java-2d


【解决方案1】:

对于圆,您使用圆的半径而不是边界,因为边界是一个矩形。 我相信在 java 中有一些方法可以做到这一点,但我还不知道,所以应该做一些研究。

另外,对于高级碰撞,人们倾向于使用向量,我以前从未摆弄过它们,所以你也必须研究一下。

这里有一些东西可以帮助你:

Java area and intersection

【讨论】:

    【解决方案2】:

    这里的问题是,正如你提到的 “hitTop() 将返回 true,因为 getY()+getHeight()&gt;=item.getY() 在这两种情况下都为 true(即球的底部边缘的 y 值大于它与之碰撞的对象的顶部边缘)。”

    为了解决这个问题,您还需要检查以确保圆的 y 位置小于游戏对象的 y 位置 + 游戏对象的高度(也可能从中减去一些偏移量)。

    应该是这样的(不用担心偏移):

    public boolean hitTop(GameItem item)
    {       
        return getY() + getHeight() >= item.getY() && 
            getY() < item.getY() + item.getHeight();     
    }
    

    您需要为所有碰撞执行此操作。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-06-26
      • 2011-09-05
      • 2019-04-30
      • 1970-01-01
      • 2014-08-12
      • 1970-01-01
      相关资源
      最近更新 更多