Frage

I implementiert den Code aus der Frage „ Kugel zu Kugel-Kollision - Erkennung und Handhabung “in Objective-C. Jedes Mal, wenn die Kugeln in einem Winkel ihre Geschwindigkeit kollidieren dramatisch erhöht. Alle der Vektor Mathematik wird mit cocos2d-iphone , mit dem Header CGPointExtension.h. Was ist die Ursache für diese unerwünschte Beschleunigung?

Das folgende ist ein Beispiel für Erhöhung der Geschwindigkeit:

Input:
Masse == 12,56637
velocity.x == 1.73199439
velocity.y == -10,5695238

ball.mass == 12,56637
ball.velocity.x == 6.04341078
ball.velocity.y == 14.2686739

Ausgabe:
Masse == 12,56637
velocity.x == 110.004326
velocity.y == -10,5695238

ball.mass == 12,56637
ball.velocity.x == -102,22892
ball.velocity.y == -72,4030228

#import "CGPointExtension.h"
#define RESTITUTION_CONSTANT (0.75) //elasticity of the system

- (void) resolveCollision:(Ball*) ball
{
    // get the mtd (minimum translation distance)
    CGPoint delta = ccpSub(position, ball.position);
    float d = ccpLength(delta);
    // minimum translation distance to push balls apart after intersecting
    CGPoint mtd = ccpMult(delta, (((radius + ball.radius)-d)/d)); 


    // resolve intersection --
    // inverse mass quantities
    float im1 = 1 / [self mass]; 
    float im2 = 1 / [ball mass];

    // push-pull them apart based off their mass
    position = ccpAdd(position, ccpMult(mtd, (im1 / (im1 + im2))));
    ball.position = ccpSub(ball.position, ccpMult(mtd, (im2 / (im1 + im2))));

    // impact speed
    CGPoint v = ccpSub(velocity, ball.velocity);
    float vn = ccpDot(v,ccpNormalize(mtd));

    // sphere intersecting but moving away from each other already
    if (vn > 0.0f) return;

    // collision impulse
    float i = (-(1.0f + RESTITUTION_CONSTANT) * vn) / ([self mass] + [ball mass]);
    CGPoint impulse = ccpMult(mtd, i);


    // change in momentum
    velocity = ccpAdd(velocity, ccpMult(impulse, im1));
    ball.velocity = ccpSub(ball.velocity, ccpMult(impulse, im2));

}
War es hilfreich?

Lösung

Ich bin derjenige, der den ursprünglichen Ballabsprung Code geschrieben Sie verwiesen. Wenn Sie herunterladen und ausprobieren dass Code, können Sie es funktioniert gut sehen.

Der folgende Code korrekt ist (die Art, wie Sie es ursprünglich hatte):

// collision impulse
float i = (-(1.0f + RESTITUTION_CONSTANT) * vn) / (im1 + im2);
CGPoint impulse = ccpMult(mtd, i);

Dies ist sehr häufig Physik Code und Sie können es wie folgt in den folgenden Beispielen fast genau umgesetzt sehen:

Das ist richtig, und es ist nicht ~ ~ einen AdR über 1,0 zu schaffen, wie andere vorgeschlagen haben. Dies wird die relative Impulsvektor-Berechnungs basierend Startmasse und der Koeffizient der Restitution.

Ignoriert Reibung, ein einfaches 1D-Beispiel ist wie folgt:

J = -Vr(1+e) / {1/m1 + 1/m2}  

Wo e Sie ist CoR, Vr ist Ihre normalisierte Geschwindigkeit und J ist ein skalarer Wert der Impulsgeschwindigkeit.

Wenn Sie etwas zu tun, weiter fortgeschritten als dies planen, empfehle ich Ihnen eine der Bibliotheken viele Physik nutzen bereits dort. Wenn ich den Code verwendet, oben war es für ein paar Kugeln in Ordnung, aber wenn ich es auf mehrere hundert hochgefahren es begann zu ersticken. Ich habe das Box2D Physik-Engine verwendet und seine Solver könnten mehr Kugeln behandeln und es ist viel genauer.

Wie auch immer, schaute ich über Ihren Code und auf den ersten Blick sieht es gut (es ist eine recht getreue Übersetzung). Es ist wahrscheinlich ein kleiner und feine Fehler eines falschen Wertes übergeben wird, oder ein Vektor mathematisches Problem.

Ich weiß nicht, etwas iPhone Entwicklung in Bezug auf, aber ich würde vorschlagen, einen Haltepunkt an der Spitze dieser Methode Einstellung und Überwachung jeden Schrittes resultierenden Wert und zu finden, wo das Blow-up ist. Stellen Sie sicher, dass die MTD korrekt berechnet wird, die Aufprallgeschwindigkeiten, etc, etc, bis Sie sehen, wo die große Zunahme eingeführt zu werden.

Bericht zurück mit den Werten der einzelnen Schritte in diesem Verfahren, und wir werden sehen, was wir haben.

Andere Tipps

den ursprünglichen Code überprüft hat und die Kommentare vom Verfasser scheint der Code gleich, so dass, wenn das Original eine korrekte Umsetzung ist, würde ich eine schlechte Vektor-Bibliothek vermuten, oder irgendeine Art von nicht initialisierten Variablen.

Warum fügen Sie 1,0 auf den Restitutionskoeffizienten?

Von: http://en.wikipedia.org/wiki/Coefficient_of_restitution

Der Ausschuß der Regionen ist in der Regel eine Zahl im Bereich [0,1]. Qualitativ stellt 1 einen perfekt elastischen Stoß, während 0 eine vollkommen unelastisch Kollision darstellt. A COR größer als eins ist theoretisch möglich, eine Kollision darstellt, die Minen geworfen zusammen und explodiert.

kinetische Energie, wie Grund und Boden erzeugt

Ein weiteres Problem ist folgende:

/ (im1 + im2)

Sie sind durch die Summe der reziproken der Massen Dividieren der Impuls entlang des Vektors der Kontakt kommen - sollten Sie wahrscheinlich durch die Summe der Massen selbst werden zu teilen. Dies wird vergrößert Ihren Impuls ( „das ist, was sie sagte“).

In dieser Zeile:

CGPoint impulse = ccpMult(mtd, i);

MTD muss normalisiert wurden. Der Fehler geschah, weil im ursprünglichen Code MTD in einer vorherigen Zeile normalisiert wurde, aber nicht in Ihrem Code. Sie können das Problem beheben, indem so etwas wie dies zu tun:

CGPoint impulse = ccpMult(ccpNormalize(mtd), i);
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top