Laden...

Ballkollision und die Vektoren

Erstellt von benpicco vor 17 Jahren Letzter Beitrag vor 17 Jahren 2.037 Views
benpicco Themenstarter:in
9 Beiträge seit 2006
vor 17 Jahren
Ballkollision und die Vektoren

Hallo, ich weiß nicht, ob das der richtige Platz ist, aber naja...
Ich wollte einen kleinen Bildschirmschoner in dem Bälle gegeneinander stoßen und abprallen schreiben. Ich fand folgenden, sehr gut funktionierenden qBasic code, der die benötigte Formel enthielt:


    'Formula:

    '1. Impact= balla-ballb         'vector subtaction

    '2. impulse = Normalize(p1,p2)  'see normalize sub

    '3. impactspeed = Dot!(impact,impulse)

    '4. newimpulse=impulse*impactspeed*mass1*mass2

    '5. newa=balla+newimpulse/mass1

    '6. newb=ballb-newimpulse/mass2

    'PS the divide by 2 is for the frictionless model. ;*)





    impactx! = balls(1).xv - balls(0).xv

    impacty! = balls(1).yv - balls(0).yv

    Normalize impulsex!, impulsey!, balls(0).x, balls(0).y, balls(1).x, balls(1).y

    impactSpeed! = Dot!(impactx!, impacty!, impulsex!, impulsey!)



    impulsex! = impulsex! * impactSpeed! * balls(0).mass * balls(1).mass / 2

    impulsey! = impulsey! * impactSpeed! * balls(0).mass * balls(1).mass / 2



    xva! = balls(0).xv + impulsex! / balls(0).mass

    yva! = balls(0).yv + impulsey! / balls(0).mass



    xvb! = balls(1).xv - impulsex! / balls(1).mass

    yvb! = balls(1).yv - impulsey! / balls(1).mass

Diesen habe ich nun nach C# portiert, leider weiß ich wenig über Vektorrechnung, daran könnte es liegen, dass die Bälle zwar im richtigen Winkel, aber mit stark überhöhter Geschwindigkeit abprallen (was am Ende dazu führt, dass sie schnell flackernd in einer ecke liegen (naja eigentlich springen sie dann pro Frame von einer Bildschirmecke zur anderen))


            float massA = (float)(Math.Pow(this.rad , 2) * Math.PI);
            float massB = (float)(Math.Pow(CollBall.rad , 2) * Math.PI);
            
            Vector2 impact  = CollBall.speed - this.speed;
            Vector2 impulse = Vector2.Normalize(new Vector2(CollBall.x-this.x,CollBall.y-this.y));
            float impactspeed = Vector2.Dot(impact, impulse);
            Vector2 newImpulse = impulse * impactspeed * massA * massB * 0.5f; 
            CollBall.speed -= newImpulse * (1f/massB);
            this.speed += newImpulse * (1f/massA);

Kann mir jemand helfen herauszufinden, wo mein Fehler liegt?

Es gibt 10 Arten von Menschen. Solche die binär denken können und solche, die es nicht können.

T
512 Beiträge seit 2006
vor 17 Jahren

Erstmal ein Problem bei dem ich ins Stutzen kam:

Die Speed Membervariablen sind Vektoren oder? Dann wäre der Name Velocity besser gewählt, Speed beschreibt eigentlich nur den Betrag der Geschwindigkeit, und nicht seine Richtung.

Aber die Formel ist eindeutig falsch. Man muss sich nur mal die Einheiten dazudenken, dann kommt am Ende für die gerichtete Geschwindigkeit was mit Gramm raus, was so nicht stimmen kann.

Imo müsste das so aussehen:


float massSum = massA + massB;
float massDiff = massA - massB;

Vector2 impulse = Vector2.Normalize(new Vector2(CollBall.x-this.x,CollBall.y-this.y));
float speedA= Vector2.Dot( impulse, this.speed );
float speedB = Vector2.Dot( impulse, CollBall.speed );
float newSpeedA = (massDiff*speedA + 2*massB*speedB) / massSum;
float newSpeedB = ((-massDiff)*speedB + 2*massA*speedA) / massSum;
this.speed += impulse * (newSpeedA - speedA);
CollBall.speed += impulse * (newSpeedB - speedB);

Das müsste so eigentlich hinhauen... vieleicht kriegst es ja noch cleverer umgeformt, aber das zeigt dem Impulserhaltungssatz glaub ich am Besten. Man zerlegt erstmal die Bewegung in die Anteile in Stoßrichtung (speedA und speedB in Richtung impulse). Dann rechnet man über Impulserhaltung und Energieerhaltung die neuen Anteile in diese Richtung aus (newSpeedA und newSpeedB in Richtung impulse).
Und die neue Bewegung ist die Summe aus den neuen Anteilen, und der Bewegung, die Senkrecht zur Stoßrichtung ist. Senkrecht zur Stoßrichtung wäre:

this.speed - impulse*speedA

die neue Bewegung addiert wäre dann:

this.speed = this.speed - impulsespeedA + impulsenewSpeedA

und etwas zusammengefasst:

this.speed += impulse*(newSpeedA - speedA)

e.f.q.

Aus Falschem folgt Beliebiges

benpicco Themenstarter:in
9 Beiträge seit 2006
vor 17 Jahren

Danke, es funktioniert wunderbar 🙂

Es gibt 10 Arten von Menschen. Solche die binär denken können und solche, die es nicht können.