2 Stimmen

Einfaches 2D-Kollisionsproblem

Ich möchte herausfinden, wann eine Kollision zwischen einem statischen und einem bewegenden Ball auftritt, aber der von mir entwickelte Algorithmus erkennt manchmal keine Kollision und der bewegende Ball geht durch den statischen hindurch. Der bewegende Ball wird von der Schwerkraft beeinflusst und der Statische nicht.

Hier ist mein Kollisionserkennungscode:

GLfloat whenSpheresCollide(const sphere2d &firstSphere, const sphere2d &secondSphere)
{
    Vector2f relativePosition = subtractVectors(firstSphere.vPosition, secondSphere.vPosition);
    Vector2f relativeVelocity = subtractVectors(firstSphere.vVelocity, secondSphere.vVelocity);

    GLfloat radiusSum = firstSphere.radius + secondSphere.radius;

    //Wir finden die Zeit, wenn Objekte kollidieren, falls eine Kollision stattfindet

    //r(t) = P[0] + t * V[0]
    //
    //d^2(t) = P[0]^2 + 2 * t * P[0] * V[0] + t^2 * V[0]^2
    //
    //d^2(t) = V[0]^2 * t^2 + 2t( P[0] . V[0] ) + P[0]^2
    //
    //d(t) = R
    //
    //d(t)^2 = R^2
    //
    //V[0]^2 * t^2 + 2t( P[0] . V[0] ) + P[0]^2 - R^2 = 0
    //
    //delta = ( P[0] . V[0] )^2 - V[0]^2 * (P[0]^2 - R^2)
    //
    //  Wir interessieren uns für die niedrigste t:
    //
    //t = ( -( P[0] . V[0] ) - sqrt(delta) ) / V[0]^2
    //

    GLfloat equationDelta = squaref( dotProduct(relativePosition, relativeVelocity) ) - squarev( relativeVelocity ) * ( squarev( relativePosition ) - squaref(radiusSum)  );

    if (equationDelta >= 0.0f)
    {
        GLfloat collisionTime = ( - dotProduct(relativePosition, relativeVelocity) - sqrtf(equationDelta) ) / squarev(relativeVelocity);

        if (collisionTime >= 0.0f && collisionTime <= 1.0f / GAME_FPS)
        {
            return collisionTime;
        }
    }

    return -1.0f;
}

Und hier ist die Aktualisierungsfunktion, die die Kollisionsabfrage aufruft:

void GamePhysicsManager::updateBallPhysics()
{
    //
    //Geschwindigkeit aktualisieren
    vVelocity->y -= constG / GAME_FPS;  //v = a * t = g * 1 Sekunde / (Aktualisierungen pro Sekunde)

    shouldApplyForcesToBall = TRUE;

    vPosition->x += vVelocity->x / GAME_FPS;
    vPosition->y += vVelocity->y / GAME_FPS;

    if ( distanceBetweenVectors( *pBall->getPositionVector(), *pBasket->getPositionVector() ) <= pBasket->getRadius() + vectorLength(*vVelocity) / GAME_FPS )
    {
        //Ball-Sphäre
        sphere2d ballSphere;
        ballSphere.radius = pBall->getRadius();
        ballSphere.mass = 1.0f;
        ballSphere.vPosition = *( pBall->getPositionVector() );
        ballSphere.vVelocity = *( pBall->getVelocityVector() );

        sphere2d ringSphereRight;
        ringSphereRight.radius = 0.05f;
        ringSphereRight.mass = -1.0f;
        ringSphereRight.vPosition = *( pBasket->getPositionVector() );
        //ringSphereRight.vPosition.x += pBasket->getRadius();
        ringSphereRight.vPosition.x += (pBasket->getRadius() - ringSphereRight.radius);
        ringSphereRight.vVelocity = zeroVector();

        GLfloat collisionTime = whenSpheresCollide(ballSphere, ringSphereRight);

        if ( collisionTime >= 0.0f )
        {
            DebugLog("Kollision");
            respondToCollision(&ballSphere, &ringSphereRight, collisionTime, pBall->getRestitution() * 0.75f );
        }

        //
        //Implementiere Auswahl der Ergebnisse, die zuerst kollidieren

        vVelocity->x = ballSphere.vVelocity.x;
        vVelocity->y = ballSphere.vVelocity.y;

        vPosition->x = ballSphere.vPosition.x;
        vPosition->y = ballSphere.vPosition.y;
    }

Warum wird die Kollision nicht in 100% der Fälle erkannt? Sie wird nur in 70% der Fälle erkannt. Danke.

UPDATE: Das Problem scheint gelöst zu sein, wenn ich die FPS von 30 auf 10 ändere. Wie beeinflusst die FPS meine Kollisionserkennung?

1voto

Seth Punkte 42154

Wie groß sind die Kugeln und wie schnell bewegen sie sich? Kann eine Kugel während eines Frames über die zweite "springen" (d. h. ist ihr Geschwindigkeitsvektor länger als ihre Breite?)

In dieser Hinsicht, was passiert, wenn Sie das obere Limit entfernen:< / p>

 ` if (collisionTime> = 0.0f && collisionTime <= 1.0f / GAME_FPS)
{
    return collisionTime;
}
` 

Wenn die Kugel zu schnell unterwegs war, erkennt Ihr Algorithmus möglicherweise eine Kollision, die vor mehr als einem Frame aufgetreten ist .. (?)

1voto

delta = ( P[0] . V[0] )^2 - V[0]^2 * (P[0]^2 - R^2)

Sollte das nicht delta = b2 - 4 ac sein?


[Edit] Ach, ich sehe. Du hast die 4 herausgezogen. In dem Fall, bist du sicher, dass du beide Lösungen für t berücksichtigst?

t = ( -( P[0] . V[0] ) - sqrt(delta) ) / V[0]^2

und

t = ( -( P[0] . V[0] ) + sqrt(delta) ) / V[0]^2

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X