2009-03-04 19 views
3

Dies ist wahrscheinlich ein wirklich grundlegendes Problem, aber ich kann anscheinend keine anderen Artikel darüber finden.Bouncing Ball in Java

Wie auch immer, ich habe ein kleines springendes Ballprogramm in Java geschrieben, um meine Grundkenntnisse zu erweitern. Das Programm ist nur eine einfache springenden Ball, der fallen wird und hoffentlich für eine Weile springen. Das ursprüngliche Programm funktionierte gut, aber jetzt habe ich versucht, die Schwerkraft in das Programm hinzuzufügen. Die Gravitation funktioniert tatsächlich eine Weile gut, aber sobald die Bounces sehr klein sind, wird die Animation für eine sehr kurze Zeit unberechenbar, dann nimmt die Position des Balls ständig ab. Ich habe versucht, das Problem herauszufinden, aber ich kann es einfach nicht sehen. Jede Hilfe wäre sehr willkommen.

public final class Ball extends Rectangle { 
float xspeed = 1.0f; float yspeed = 1.0f; float gravity = 0.4f; 


public Ball(float x, float y, float width, float height) { 
    super(x, y, width, height); 
} 

public void update(){ 
    yspeed += gravity; 

    move(xspeed, yspeed); 

    if(getX() < 0){ 
     xspeed = 1; 
    } 
    if(getX() + getWidth() > 320){ 
     xspeed = -1; 
    } 
    if(getY() < 0){ 
     yspeed = 1; 
    } 
    if(getY() + getHeight() > 200 && yspeed > 0){ 
     yspeed *= -0.98f; 
    } 
    if(getY() + getHeight() > 200 && yspeed < 0){ 
     yspeed *= 0.98f; 
    } 

} 

public void move(float x, float y){ 
    this.setX(getX()+x); 
    this.setY(getY()+y); 
} 

}

EDIT: Danke, die die erratische Bewegung sortiert zu haben scheint. Ich habe immer noch Schwierigkeiten zu sehen, wie ich meinen Ball stoppen kann, wenn er nicht mehr springt. Gerade jetzt wird es sich bewegen, um zu springen, dann weiter nach unten über den "Boden". Ich denke, dass es mit meiner Yspeed + = Gravitationslinie zu tun hat. Ich kann einfach nicht sehen, wie ich die Bewegung stoppen würde.

Antwort

3

Wenn Sie das tun

yspeed += gravity; 

Sie vorausgesetzt, dass der Ball durch den Raum bewegt einen Abstand dx = v_i * t + 1/2 (-G) T^2. Wenn Sie sehr nahe am Boden sind, ist dies möglicherweise nicht wahr. Es schlägt fehl, wenn:

  • Sie nahe genug sind der Boden und
  • Sie sind sehr nahe dem Boden nach unten bewegen und haben eine niedrige Geschwindigkeit (wie, wenn der Ball das meiste davon ist Energie verloren hat)

Dieser Fehler führt dazu, dass Ihre Simulation keine Energie mehr speichert, was zu einem unberechenbaren Verhalten bei niedriger Amplitude führt.

können Sie das Problem verringern, indem sie kleinere Zeitschritte verwendet, und Sie können völlig loswerden, wenn Sie Test Berechnung tun zu bemerken, wenn Sie aus dem Zimmer sind und einen sicheren Zeitschritt für dass Iteration auszuwählen (Verwenden Sie also immer Ihren Standard, sofern kein Problem vorliegt, und berechnen Sie dann den besten Zeitschritt.

Die grundlegende Annäherung, die Sie hier verwenden, hat jedoch auch andere Probleme. Suchen Sie in einem numerischen Analysetext nach einer Diskussion zum numerischen Lösen von Differentialgleichungen.

1

Ich vermute, es ist, weil wenn der Ball springt, wird es tatsächlich etwas unter dem "Boden" sein, und bei niedrigen Geschwindigkeiten wird es nicht über den Boden in einem Tick zurück - so das nächste Update() sehen es immer noch unter der Erde, und hüpfen wieder - aber nach unten dieser Zeit, so wird der Zyklus fortgesetzt.

Sie müssen den Ball wieder auf dem Boden bewegen, wenn es springt, so etwas wie diese:

if(getY() + getHeight() > 200){ 
      yspeed *= -0.981; 
      setY(200 - getHeight()); 
    } 
+0

bewegen scheint Deltas zu nehmen, keine absoluten Werte, ist der Ball wahrscheinlich den Rand des Universums :-) – paxdiablo

+0

heh fliegen , Hoppla. Fest. – Blorgbeard

1

Das Wichtigste zuerst: Einstellung y-Geschwindigkeit auf 1, wenn Sie auf dem oberen Rand des Fensters springen ist nicht korrekt, du solltest yspeed auf -yspeed setzen (aber wenn du innerhalb der Grenzen anfängst, sollte es sowieso niemals nach oben springen).

Zweitens multiplizieren Sie mit -0.981, wenn ich auf den Boden hüpfe, ist in Ordnung, aber ich bin besorgt, dass die konstante 0,4-Gravitation in jeder Iteration zu yspeed addiert wird. Ich denke, das ist es, was dazu führt, dass du am Boden wackelst, da du den Zug machst, bevor du kontrollierst, was dazu führen kann, dass der Ball unter den Boden fällt.

ich versuchen würde, die die y-Wert zu gewährleisten nie durch Ersetzen der Bewegung unter der Erde gehen:

if (getY() + getHeight() + yspeed > 200) { 
    move(xspeed, 200 - getY() - getHeight()); 
} else { 
    move(xspeed, yspeed); 
} 
1

Das Problem ist, dass, wenn die Bounces bekommen wirklich klein, die

yspeed *= -0.981; 

Zeile wird in kurzer Folge aufgerufen. Der Ball wird unter den Boden gehen, anfangen, wieder aufzustehen, aber immer noch unter dem Boden sein (weil 0.981 < 1.0) schließlich, und es wird sich beklagen. Hier ist, wie man es beheben:

if(getY() + getHeight() > 200){ 
    yspeed *= -0.981; 
    setY(400 - getY() - getHeight()); // I believe this is right. 
} 

Durch die Position zu fixieren, werden Sie nicht wechseln zwischen abnimmt und so schnell zu und wird nicht in der Situation stecken, wo es immer abnimmt, weil es immer unterhalb der Grenzen ist .

+0

200 - (getY() + getHeight() - 200) = 200 - getY() - getHeight() + 200 = 400 - getY() - getHeight() – qpingu

1

[EDIT: Ich glaube, ich falsch verstanden, so ist dies wahrscheinlich nicht viel :)]

if(getY() + getHeight() > 200){ 
    yspeed *= -0.981; 
} 

Sie negiert die vertikale Geschwindigkeit bei jedem Update. Ich würde wahrscheinlich versuchen, Schwerkraft in Update-Größe Scheiben zu behandeln. Angenommen, Sie sind dabei 30 Updates pro Sekunde (für 30 fps), vielleicht so etwas wie

// Define some constants 
SecondsPerUpdate = (1.0f/30); 
AccelDueToGravity = 0.981; 

if(getY() + getHeight() > 200){ 
    yspeed -= (AccelDueToGravity * SecondsPerUpdate); 
}