使用边界框进行碰撞检测 [英] Collision Detection using bounded boxes

查看:101
本文介绍了使用边界框进行碰撞检测的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在上课的编程项目。我们正在编写游戏突破的程序,其中包括一个球,一个球拍,四个边缘和一个砖块。当检测到碰撞时,球会从不同的物体反弹,并且每个物体对其自身执行不同的操作。以下是我的当前无效的代码。我正在尝试使用对象的位置(其中心点)构造一个有边界的框,并使用每个边缘(上,下,左,右)的值来计算该框是否命中。我脑子里想出可能有两种类型的碰撞,一种是角点碰撞,另一种是一个物体撞到另一个物体中间的某个地方。请仔细检查我的代码,并寻求帮助。我不知道是否有更好的方法来做我想做的事情,但是我目前无法使用,并且几乎一直都返回true值。

I'm doing a programing project for class. We are programing the game break out, which consist of a ball, a paddle, four edges, and bricks. the ball bounces off the different objects and each object preforms different operations upon itself when a collision is detected. below is my code which currently doesn't work. I'm trying to use the location of the object (its center point) to construct a bounded box and the values of each edge(Top, Bottom, Left, Right) to calculate if the boxes hit. I figured in my head that there could be two types of collisions one where the corners hit and one where one object hits somewhere in the middle of the other object. Please look over my code and help if you can. I don't know if there is a better way to do what I'm trying to do but what I have currently doesn't work and returns a value of true pretty much all the time.

这是代码的一部分,它检查每个能够碰撞的对象与其他所有可能碰撞的对象。

This is the part of the code that checks every object that is able to collide with every other object that can collide. it also moves each object and ticks the game's clock.

/**
     * Tell the GameWorld that the "game clock" has ticked. A clock tick in the GameWorld has the 
     * following effects: (1) all movable objects are told to update their positions according to there 
     * current heading and speed, (2) the "elapsed game time" is incremented by one and (3) all Items are 
     * checked for a collision.
     */
    public void tickClock() {
        gameClock++;
        Iterator theElements0 = listOfGameObjects.getIterator();
        while (theElements0.hasNext()){
            GameObject gObj = (GameObject) theElements0.getNext();
            if ( gObj instanceof IMovable){
                IMovable mObj = (IMovable)gObj;
                mObj.move(gameClock);
            }
        }
        Iterator theElements1 = listOfGameObjects.getIterator();
        while (theElements1.hasNext()){
            GameObject gObj0 = theElements1.getNext();//get a collidable object.
            if(gObj0 instanceof ICollider){
                ICollider curObj = (ICollider) gObj0;
                //check if this object collides with any OTHER object.
                Iterator theElements2 = listOfGameObjects.getIterator();
                while(theElements2.hasNext()){
                    GameObject gObj1 = theElements2.getNext();
                    if(gObj1 != curObj && gObj1 instanceof ICollider) {
                        ICollider otherObj = (ICollider) gObj1;
                        if (curObj.collidesWith(otherObj)){
                            curObj.handleCollision(otherObj);
                        }
                    }
                }   
            }
        }
        setChanged();
        notifyObservers();
    }

这是代码的一部分,用于确定对象是否具有与另一个物体相撞,如果有的话,还要采取适当的措施。这部分代码是专门从球形物体发出的,因此当它撞到一块砖块时执行的动作是ySpeed反转。

This is the part of the code that is used to determine if an object has collided with another object and also the appropriate action to take if it has. This section of code is from the ball object specifically, so the action preformed when it hits a brick is the ySpeed is reversed.

public boolean collidesWith(ICollider otherObj) {
        GameObject gObj = (GameObject) otherObj;
        //this collider
        int r1 = (int) (getX() + getWidth()/2);
        int l1 = (int) (getX() - getWidth()/2);
        int t1 = (int) (getY() + getHeight()/2);
        int b1 = (int) (getY() - getHeight()/2);

        //the other collider
        int r2 = (int) (gObj.getX() + gObj.getWidth()/2);
        int l2 = (int) (gObj.getX() - gObj.getWidth()/2);
        int t2 = (int) (gObj.getY() + gObj.getHeight()/2);
        int b2 = (int) (gObj.getY() - gObj.getHeight()/2);

        //corner collision check
        if(r1>l2 && t2>b1 && t1>t2 && b1>b2){
            System.out.println("Corner Collision check 1");
            return true;
        }
        if(r2>l1 && t2>b1 && t1>t2 && b1>b2){
            System.out.println("Corner Collision check 2");
            return true;
        }
        if(r2>l1 && t1>b2 && t2>t1 && b2>b1){
            System.out.println("Corner Collision check 3");
            return true;
        }
        if(r1>l2 && t1>b2 && t2>t1 && b2>b1){
            System.out.println("Corner Collision check 4");
            return true;
        }

        //middle collision check
        if(l1>l2 && r1<r2 && t1<t2 && b1<b2){
            System.out.println("middle collision check 1");
            return true;
        }
        if(l1>l2 && r1<r2 && t1>t2 && b1>b2){
            System.out.println("middle Collision check 2");
            return true;
        }
        if(l1<l2 && r1<r2 && t1<t2 && b1>b2){
            System.out.println("middle Collision check 3");
            return true;
        }
        if(l1>l2 && r1>r2 && t1<t2 && b1>b2){
            return true;
        }

        return false;
    }

    public void handleCollision(ICollider otherObject) {
        if(otherObject instanceof Brick){
            System.out.println("Brick Hit");
            ySpeed = -(ySpeed);
        }
    }


推荐答案

您只需要检查边界框的 edges

You only need to check the edges of the bounding box. Some pseudo code could look like.

if Rect1[RIGHT] < Rect2[LEFT] or
   Rect1[LEFT] > Rect2[RIGHT] or
   Rect1[TOP] < Rect2[BOTTOM] or
   Rect1[BOTTOM] > Rect2[TOP]
then return false
else return true

这是什么试图说的是,如果X或Y坐标系之间有任何可能的间隙将框分隔开,则不可能发生碰撞。这是 SAT(分离轴定理)的非常简单的版本。

What this is trying to say is that if there are any possible gaps along the X or Y coordinate system separating the boxes then a collision is not possible. This is a very simple version of the SAT (Separating Axis Theorem)

在视觉上看起来像这样的小图像,这里也应用了相同的想法。

A little image of what this looks like visually, the same idea is applied here also.

这应表示类似于以下应该工作。请注意,我尚未对其进行测试,但是可以引导您朝着正确的方向前进。

This should mean that something similar to the following should work. Please note I haven't testing it but could lead you in the right direction.

public boolean collidesWith(ICollider otherObj) {
    GameObject gObj = (GameObject) otherObj;
    //this collider
    int r1 = (int) (getX() + getWidth()/2);
    int l1 = (int) (getX() - getWidth()/2);
    int t1 = (int) (getY() + getHeight()/2);
    int b1 = (int) (getY() - getHeight()/2);

    //the other collider
    int r2 = (int) (gObj.getX() + gObj.getWidth()/2);
    int l2 = (int) (gObj.getX() - gObj.getWidth()/2);
    int t2 = (int) (gObj.getY() + gObj.getHeight()/2);
    int b2 = (int) (gObj.getY() - gObj.getHeight()/2);

    if (r1 < l2 || l1 > r2 || t1 < b2 || b1 > t2)
       return false;
    else
       return true;

    /* Or could be shortened down to
    return !(r1 < l2 || l1 > r2 || t1 < b2 || b1 > t2) */

}

您说的不是很多代码;)

quite a reduction in code wont you say ;)

这篇关于使用边界框进行碰撞检测的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆