Frage

ich eine ziemlich einfache Java-Anwendung geschrieben haben, die Sie mit der Maus und auf der Länge der Maus per Drag basiert ziehen können Sie tat, wird er einen Ball in diese Richtung schießen, Wände abprallen, wie es geht.

Hier ist ein kurzer Screenshot:
alt text http://img222.imageshack.us/img222/3179/ballbouncemf9.png

Jeder der Kreise auf dem Bildschirm ist ein Ball-Objekt. Die Kugeln Bewegung gliedert sich in eine x-und y-Vektor;

public class Ball {
    public int xPos;
    public int yPos;
    public int xVector;
    public int yVector;

    public Ball(int xPos, int yPos, int xVector, int yVector) {
        this.xPos = xPos;
        this.yPos = yPos;
        this.xVector = xVector;
        this.yVector = yVector;
    }

    public void step()
    {
        posX += xVector;
        posY += yVector;

        checkCollisions();
    }

    public void checkCollisions()
    {
        // Check if we have collided with a wall
        // If we have, take the negative of the appropriate vector
        // Depending on which wall you hit
    }

    public void draw()
    {
        // draw our circle at it's position
    }
}

Dies funktioniert gut. Alle Bälle hüpfen herum und herum von Wand zu Wand.

Allerdings habe ich entschieden, dass ich die Wirkung der Schwerkraft in der Lage sein möchten. Ich weiß, dass Objekte bei 9,8 m / s auf der Erde beschleunigen, aber ich weiß nicht direkt wissen, wie dies in Code übersetzen sollte. Mir ist klar, dass die yVector betroffen sein werden, aber meine Experimente mit diesem haben nicht den gewünschten Effekt, den ich wollte.

Im Idealfall, Ich möchte in der Lage sein, einige Schwerkraftwirkung auf dieses Programm hinzuzufügen und damit auch die Kugeln ein paar Mal auf die Beine, bevor mit dem Absetzen „Boden“.

Wie kann ich dieses Prellen-elastisch, Schwerkraftwirkung schaffen? Wie muß ich bei jedem Schritt der Geschwindigkeitsvektoren des Balls manipulieren? Was muss getan werden, wenn es die „Masse“ trifft, so dass ich zulassen kann es wieder auf die Beine, aber etwas kürzer als die vorherige Zeit?

Jede Hilfe sehr geschätzt wird mich in der richtigen Richtung in zeigen.


Vielen Dank für die Kommentare alle! Es arbeitet bereits groß!

In meinem Schritt () Ich füge eine Gravitationskonstante zu meinem yVector wie Leute vorgeschlagen und dies ist mein checkCollision ():

public void checkCollision()
{
    if (posX - radius < 0)              // Left Wall?
    {
        posX = radius;              // Place ball against edge
        xVector = -(xVector * friction);
    }
    else if (posX + radius > rightBound) // Right Wall?
    {
        posX = rightBound - radius;     // Place ball against edge
        xVector = -(xVector * friction);
    }

    // Same for posY and yVector here.
}

Allerdings werden die Kugeln weiter um / Rolle auf dem Boden gleiten. Ich nehme an, das ist, weil ich bin einfach einen Prozentsatz (90%) ihre Vektoren jeden Prell nehmen und es ist nie wirklich Null. Soll ich in einem Scheck hinzufügen, dass, wenn der xVector einen gewissen Absolutwert wird, ich soll es nur auf Null ändern?

War es hilfreich?

Lösung

Was Sie tun müssen, ist ständig eine kleine Konstante subtrahiert (etwas, das Ihre 9,8 m / s entspricht) von Ihrem yVector. Wenn der Ball geht nach unten (yVector ist bereits negativ), dies würde es schneller gehen. Wenn es geht nach oben (yVector positiv ist), es wäre es verlangsamen.

Dies würde nicht für Reibung, so sollten die Dinge so ziemlich prallen für immer.

edit1: Zur Berücksichtigung Reibung, wann immer es umkehrt (und Sie kehren die Vorzeichen), senken die absolute Zahl ein wenig. Wie, wenn es bei yVector = -500 trifft, wenn Sie die Zeichen umgekehrt, macht es +480 statt +500. Sie sollten wahrscheinlich die gleiche Sache tun xVector ihn zu stoppen von Seite zu Seite springen.

edit2: Auch, wenn Sie darauf reagieren wollen „Luftreibung“, reduzieren beide Vektoren durch eine sehr kleine Menge jeder Einstellung.

EDIT3: Über das, was auf dem Boden wälzen immer - Je nachdem, wie hoch Ihre Zahlen sind, könnte es eines von zwei Dingen sein. Entweder Ihre Zahlen sind groß und es scheint nur eine Ewigkeit dauern zu beenden, oder Sie runden und Ihre Vektoren sind immer 5 oder so etwas. (90% von 5 ist 4,5, so dass es bis 5 aufrunden kann).

ich eine Debug würde Erklärung ausdrucken und sehen, was die Vector Zahlen sind wie. Wenn sie um 5 bis irgendwo gehen und nur dort bleiben, dann können Sie eine Funktion verwenden, die Ihre Fraktion bis 4 kürzt statt zurück zum 5. Runden Wenn es geht immer weiter nach unten und schließlich stoppen, dann könnten Sie Ihre Reibungskoeffizienten erhöhen müssen .

Wenn Sie nicht eine einfache „Abrundung“ -Funktion finden, könnten Sie (0,9 * Vector) verwenden -. 1, Subtrahieren von 1 von Ihrer bestehenden Gleichung soll das gleiche tun

Andere Tipps

Wenn die Kugeln sind alle auf dem Boden herum rollen, ja, überprüfen Sie, ob die Geschwindigkeit unter einem bestimmten Minimalwert ist, und wenn ja, ist es auf Null gesetzt. Wenn man sich die Physik hinter dieser Art von idealisierten Bewegung suchen und vergleichen mit dem, was in der realen Welt geschieht, werden Sie sehen, dass eine einzige Gleichung nicht für die Tatsache verwendet werden kann, zu berücksichtigen, dass eine echte Kugel nicht mehr bewegt.

BTW, was Sie tun, ist das Euler-Verfahren zur numerischen Integration genannt. Es geht so:

  • Beginnen Sie mit den kinematischen Bewegungsgleichungen:
    x (t) = x0 + vx * t + 0,5 * ax t ^ 2
    y (t) = y0 + vy
    t + 0,5 * ay t ^ 2
    vx (t) = vx0 + ax
    t
    vy (t) = VY0 + ay * t
    Wobei x und y-Position, Vx und Vy sind Geschwindigkeit, Beschleunigung Ax und Ay sind, und t ist die Zeit. x0, y0, vx0 und VY0 sind die Anfangswerte. Dies beschreibt die Bewegung eines Objekts in Ermangelung einer äußeren Kraft.

  • Schwerkraft anwenden:
    ay = -9,8 m / s ^ 2
    Bis zu diesem Punkt gibt es keine Notwendigkeit, etwas zu tun schwierig. Wir können für die Position jeder Kugel lösen diese Gleichung für jederzeit mit.

  • Jetzt Luftreibung hinzufügen: Da es sich um eine sphärische Kugel ist, können wir annehmen, dass es einen Reibungskoeffizienten c hat. Es ist in der Regel zwei Möglichkeiten, wie die Luftreibung zu modellieren. Es kann auf die Geschwindigkeit oder zum Quadrat der Geschwindigkeit proportional. Lassen Sie uns den Platz verwenden:
    ax = -c vx ^ 2
    ay = -c
    vy ^ 2-9,8
    Da die Beschleunigung nun abhängig von der Geschwindigkeit ist, die nicht konstant ist, müssen wir integrieren. Das ist schlecht, weil es keine Möglichkeit gibt, diese von Hand zu lösen. Wir werden numerisch integrieren müssen.

  • Wir nehmen diskrete Zeitschritte, dt. Für die Eulersche Verfahren ersetzen wir einfach alle Vorkommen von t in den obigen Gleichungen mit dt, und verwenden Sie den Wert aus dem vorherigen Zeitschritt anstelle der Anfangswerte, x0, y0, etc. So jetzt unsere Gleichungen wie folgt aussehen (in Pseudo-Code) :

    // speichern zurück Werte
    Xalt = x;
    yold = y;
    vxold = vx;
    vyold = vy;
    // Update-Beschleunigung
    ax = -c vxold ^ 2;
    ay = -c
    vyold ^ 2-9,8;
    // Update-Geschwindigkeit
    vx = vxold + ax dt;
    vy = vyold + ay
    dt;
    // Update-Position
    x = Xalt + vxold * dt + 0,5 * ax dt ^ 2;
    y = yold + vyold
    dt + 0,5 * ay * dt ^ 2;

Dies ist eine Annäherung, so ist es nicht ganz richtig sein, aber es wird OK aussehen. Das Problem ist, dass für größere Zeitschritte, die Fehler zu, so dass, wenn wir genau modellieren, wie ein echter Ball bewegen würde, würden wir haben sehr kleine Werte für dt zu verwenden, die Probleme mit der Genauigkeit auf einem Computer verursachen würde. Zu lösen, gibt es kompliziertere Techniken. Aber wenn Sie nur das Verhalten wollen, um zu sehen, die wie die Schwerkraft und Reibung zur gleichen Zeit sieht, dann Eulersche Methode ist in Ordnung.

Jedes Mal, in Scheiben schneiden Sie müssen die Auswirkungen der Schwerkraft auf die sich die Kugel in Teh y Richtung nach unten beschleunigt. Wie Bill K vorgeschlagen, das ist so einfach wie eine Subtraktion von Ihrem „yVector“ zu machen. Wenn der Ball den Boden trifft, yVector = -yVector, jetzt bewegt es nach oben, sondern nach wie vor nach unten -BESCHLEUNIGUNG. Wenn Sie die Kugeln schließlich stoppen Prellen machen wollen, müssen Sie die Kollisionen leicht unelastisch machen, im Grunde durch eine gewisse Geschwindigkeit in y-Richtung nach oben zu entfernen, möglicherweise durch anstelle von „yVector = -yVector“, macht es „yVector = -0,9 * yVector“.

public void step()
{
    posX += xVector;
    posY += yVector;

    yVector += g //some constant representing 9.8

    checkCollisions();
}

in checkCollisions (), sollten Sie invertieren und multiplizieren yVector durch eine Zahl zwischen 0 und 1, wenn es auf den Boden prallt. Dies sollten Sie den gewünschten Effekt

Es ist eine ballistische Bewegung. Also haben Sie eine lineare Bewegung auf der x-Achse und eine einheitliche beschleunigte Bewegung auf der y-Achse.

Die Grundidee ist, dass die y-Achse der Gleichung wie folgt vor:

y = y0 + v0 * t + (0.5)*a*t^2

Oder in C-Code, zum Beispiel:

float speed = 10.0f, acceleration = -9.8f, y = [whatever position];

y += speed*t + 0.5f*acceleration*t^2;

Wo hier verwende ich TIEM Parametrisierung. Aber man kann Torricelli- verwenden:

v = sqrt(v0^2 + 2*acceleration*(y-y0));

Und auf diesem Modell, müssen Sie die letzten Werte von v und y halten.

Schließlich Ich habe etwas ähnliches mit dem ersten Modell mit dt (Zeitdifferential) durchgeführt wird bei 1/60 Sekunde festgelegt (60 FPS).

Nun, beiden Modelle geben gute Echt wie Ergebnisse, aber sqrt (), zum Beispiel, ist teuer.

Sie wirklich wollen, um zu simulieren, was die Schwerkraft tut - das alles ist Kraft schafft, die im Laufe der Zeit dient dazu, die Geschwindigkeit eines Objekts zu ändern. Jedes Mal, wenn Sie einen Schritt, ändern Sie die Geschwindigkeit des Balls ein wenig, um es auf dem Boden des Widget zu „ziehen“.

Um die keine reibungs / hüpfenden Ball absetzt Thema zu befassen, müssen Sie die „Boden“ Kollision machen eine andere Wirkung ausübt als nur strenge Reflexion - es sollte eine gewisse Menge an Energie aus der Kugel entfernen, es prallen machen bei einer geringeren Geschwindigkeit zurück, nachdem er auf den Boden, als es sonst der Fall wäre trifft.

Eine andere Sache, die Sie in der Regel in dieser Art von federnd Visualisierungen tun möchten, ist der Boden etwas seitwärts Reibung als auch geben, so dass, wenn es auf den Boden die ganze Zeit trifft, wird es schließlich zum Stillstand rollen.

Ich bin damit einverstanden mit dem, was „Bill K“ sagte, und füge hinzu, dass, wenn man sie „setzen“ zu wollen, um die x- und y-Vektoren über die Zeit zu reduzieren, muß (gilt Widerstand). Das wird eine sehr kleine Menge zu einer Zeit sein, so können Sie Ihre Vektoren von int in einen Fließkommatyp verändern müssen, oder sie nur um 1 alle paar Sekunden zu reduzieren.

Was Sie wollen, zu tun ist, um die Werte von xVector und yVector ändern Schwerkraft und Reibung zu simulieren. Das ist wirklich ziemlich einfach zu tun. (Notwendigkeit, alle Ihrer Variablen zu Schwimmern zu ändern. Wenn es darum geht, zu ziehen, nur um den Schwimmer.)

In Ihrer Funktion Schritt, nach der Ballposition zu aktualisieren, sollten Sie etwas tun, wie folgt:

yVector *= 0.95;
xVector *= 0.95;
yVector -= 2.0;

Diese skaliert die X- und Y-Geschwindigkeit leicht nach unten, so dass Sie Ihre Bälle schließlich bewegen zu stoppen, und wendet dann eine konstante nach unten „Beschleunigung“ der Y-Wert, der die „Verlangsamung“ schneller anreichern als und führen die Kugeln fallen .

Dies ist eine Annäherung von dem, was Sie wirklich tun wollen. Was Sie wirklich wollen, ist ein Vektor zu halten, die Beschleunigung Ihrer Kugeln repräsentieren. Jeder Schritt würden Sie dann Produkt dot, die mit einem konstanten Gravitationsvektor Vektor zu leicht die Ballbeschleunigung zu ändern. Aber ich denke, dass meine komplexer sein als Sie erhalten möchten, wenn Sie für eine realistischere Physik-Simulation suchen.

  

Was getan werden muss, wenn er trifft die   „Boden“, so dass ich zulassen kann es zu   hüpfen wieder

Wenn Sie davon ausgehen, eine perfekte Kollision (dh die gesamte Energie konserviert ist) alles, was Sie zu tun haben, kehren die Vorzeichen eines der Geschwindigkeit Skalar je nachdem, welche Wand getroffen wurde.

Zum Beispiel, wenn der Ball den rechten oder linken Wände Revese die x skalaren Komponente und lassen Sie die die y skalare Komponente gleich:

 this.xVector = -this.xVector;

Wenn der Ball die oberen oder unteren Wände der y skalare Komponente umkehren und die x skalare Komponente die gleiche verlassen:

 this.yVector = -this.yVector;
  

aber etwas kürzer als die vorherigen   Zeit?

In diesem Szenario ein Teil der Energie wird bei der Kollision mit der Wand verloren werden, so fügen Sie einfach in einem Verlustfaktor von einigen der Geschwindigkeit zu nehmen jedes Mal, wenn die Wand geschlagen wird:

 double loss_factor = 0.99;
 this.xVector = -(loss_factor * this.xVector);
 this.yVector = -(loss_factor * this.yVector;
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top