4

私はクラスのプログラミングプロジェクトを行っています。ボール、パドル、4 つのエッジ、およびレンガで構成されるゲーム ブレーク アウトをプログラムしています。ボールはさまざまなオブジェクトから跳ね返り、衝突が検出されると、各オブジェクトはそれ自体に対してさまざまな操作を実行します。以下は、現在動作しない私のコードです。オブジェクトの位置 (中心点) を使用して境界ボックスを作成し、各エッジ (上、下、左、右) の値を使用してボックスがヒットするかどうかを計算しようとしています。私は頭の中で、コーナーが衝突する衝突と、あるオブジェクトが他のオブジェクトの真ん中のどこかに衝突する衝突の 2 つのタイプがあると考えました。私のコードを見て、できれば助けてください。私がやろうとしていることを行うためのより良い方法があるかどうかはわかりませんが、私が現在持っているものはありません.

これは、衝突できる他のすべてのオブジェクトと衝突できるすべてのオブジェクトをチェックするコードの一部です。また、各オブジェクトを動かし、ゲームのクロックを刻みます。

/**
     * 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 が逆になります。

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);
        }
    }
4

1 に答える 1

9

バウンディング ボックスのエッジを確認するだけで済みます。いくつかの疑似コードは次のようになります。

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 (分離軸定理)の非常に単純なバージョンです。

これが視覚的にどのように見えるかの小さなイメージ。ここでも同じアイデアが適用されます。

SATの可視化

これは、次のようなものが機能することを意味します。私はそれをテストしていませんが、正しい方向に導くことができることに注意してください.

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) */

}

コードのかなりの削減は言うまでもありません ;)

于 2012-04-23T23:14:18.473 に答える