Hallo,
ich habe ein kniffliges Anliegen:
Ich lasse einen Ball aus einer bestimmten Höhe herunterfallen mit einer konfigurierbaren Schwerkraft. Verwende ich die normale Erdbeschleunigung ~9.8m/s², dann prallt der Ball einmal stärker vom Boden ab, und kommt dann sehr schnell zum Stillstand (beim 3. Aufprall). Die Animation (die ich im Android-SDK-Emulator verfolge) sieht schon mal ganz ordentlich und natürlich aus. Es gibt allerdings eine Sache, die mich stört. Der Ball hat immer das selbe Gewicht, d.h. eine niedrigere Anziehungskraft lässt ihn zwar höher und öfter aufspringen, aber die Balleigenschaft lässt sich so nicht beeinflussen, wodurch man dem Ball auch nicht die Eigenschaft eines Ping-Pong-Balls oder eines Medizinballs zuweisen kann. Ich denke dabei an eine Bewegung, die in etwa so aussieht:
http://www.kirupa.com/developer/as3/physics_bounce_effect_pg1.htm
Aktuell berechne ich den Rückprall vom Boden so, dass die Geschwindigkeit der kinetischen Energie mit jener der potenziellen gleich ist. Ich setze also die Formeln gleich. Dadurch kürzt sich aber die Masse weg:
Potentielle Energie: mgh
//g...Gravitation, m...Masse des Körpers in kg, h...Höhe, um die das Objekt angehoben wird
Kinetische Energie: mv²/2
//m...Masse des Objekts in kg, v....Geschwindigkeit in m/s²
Ergebnis: v = Wurzel(2*|aktuelleHöhe-Anfangshöhe|)
Der Trick dabei ist, dem Ball irgendwie die "Eigenschaft" eines Ping-Pong-Balls zu geben, wodurch die Geschwindigkeit beim Abprallen dementsprechend beeinflusst wird. Die Preisfrage ist wie schaffe ich das?
Hier ein kurzes Testprogramm, das die Variablen ausgibt, damit die Sprungparabeln veranschauchlicht werden können.
import java.text.DecimalFormat;
public class Physics {
private int height = 0;
private double gravity = 9.8;
private double t;
private int initialY;
private double initialSpeed;
private int y;
private int lastY;
private int stageHeight = 500;
private int ballHeight = 10;
private boolean ballDirection = true;
private DecimalFormat df;
public Physics() {
y = initialY = 0;
df = new DecimalFormat("0.00");
}
public void printData() {
for (int i = 0; i < 400; i++) {
checkBottomCollision();
t+=0.2;
lastY = y;
if (ballDirection == true)
y = (int)(initialY + 0.5 * gravity * (t * t)+0.5);
else
y = (int)(initialY - initialSpeed * t + 0.5 * gravity * (t * t)+0.5);
if (lastY <= y && ballDirection == false) {
initialY = y;
ballDirection = true;
t = 0;
}
System.out.println("y:" + y + "\t| t:" + df.format(t) + "\t| initSpeed:" + df.format(initialSpeed) + "\t| Direction:" + ballDirection);
}
}
private void checkBottomCollision() {
if (y + ballHeight >= stageHeight && ballDirection == true) {
initialSpeed = Math.sqrt(2*Math.abs(y - initialY));
ballDirection = false;
initialY = y;
t = 0.0;
}
}
}
------
public class Main {
public static void main(String[] args) {
Physics p = new Physics();
p.printData();
}
}
Die Ausgabe sieht dann zB so aus. Anhand der Richtung (true/false) erkennt man sehr schön, wie und wie oft der Ball aufprallt:
y:0 | t:0,20 | initSpeed:0,00 | Direction:true
y:1 | t:0,40 | initSpeed:0,00 | Direction:true
y:2 | t:0,60 | initSpeed:0,00 | Direction:true
y:3 | t:0,80 | initSpeed:0,00 | Direction:true
y:5 | t:1,00 | initSpeed:0,00 | Direction:true
y:7 | t:1,20 | initSpeed:0,00 | Direction:true
y:10 | t:1,40 | initSpeed:0,00 | Direction:true
y:13 | t:1,60 | initSpeed:0,00 | Direction:true
y:16 | t:1,80 | initSpeed:0,00 | Direction:true
y:20 | t:2,00 | initSpeed:0,00 | Direction:true
y:24 | t:2,20 | initSpeed:0,00 | Direction:true
y:28 | t:2,40 | initSpeed:0,00 | Direction:true
y:33 | t:2,60 | initSpeed:0,00 | Direction:true
y:38 | t:2,80 | initSpeed:0,00 | Direction:true
y:44 | t:3,00 | initSpeed:0,00 | Direction:true
y:50 | t:3,20 | initSpeed:0,00 | Direction:true
y:57 | t:3,40 | initSpeed:0,00 | Direction:true
y:64 | t:3,60 | initSpeed:0,00 | Direction:true
y:71 | t:3,80 | initSpeed:0,00 | Direction:true
y:78 | t:4,00 | initSpeed:0,00 | Direction:true
y:86 | t:4,20 | initSpeed:0,00 | Direction:true
y:95 | t:4,40 | initSpeed:0,00 | Direction:true
y:104 | t:4,60 | initSpeed:0,00 | Direction:true
y:113 | t:4,80 | initSpeed:0,00 | Direction:true
y:123 | t:5,00 | initSpeed:0,00 | Direction:true
y:132 | t:5,20 | initSpeed:0,00 | Direction:true
y:143 | t:5,40 | initSpeed:0,00 | Direction:true
y:154 | t:5,60 | initSpeed:0,00 | Direction:true
y:165 | t:5,80 | initSpeed:0,00 | Direction:true
y:176 | t:6,00 | initSpeed:0,00 | Direction:true
y:188 | t:6,20 | initSpeed:0,00 | Direction:true
y:201 | t:6,40 | initSpeed:0,00 | Direction:true
y:213 | t:6,60 | initSpeed:0,00 | Direction:true
y:227 | t:6,80 | initSpeed:0,00 | Direction:true
y:240 | t:7,00 | initSpeed:0,00 | Direction:true
y:254 | t:7,20 | initSpeed:0,00 | Direction:true
y:268 | t:7,40 | initSpeed:0,00 | Direction:true
y:283 | t:7,60 | initSpeed:0,00 | Direction:true
y:298 | t:7,80 | initSpeed:0,00 | Direction:true
y:314 | t:8,00 | initSpeed:0,00 | Direction:true
y:329 | t:8,20 | initSpeed:0,00 | Direction:true
y:346 | t:8,40 | initSpeed:0,00 | Direction:true
y:362 | t:8,60 | initSpeed:0,00 | Direction:true
y:379 | t:8,80 | initSpeed:0,00 | Direction:true
y:397 | t:9,00 | initSpeed:0,00 | Direction:true
y:415 | t:9,20 | initSpeed:0,00 | Direction:true
y:433 | t:9,40 | initSpeed:0,00 | Direction:true
y:452 | t:9,60 | initSpeed:0,00 | Direction:true
y:471 | t:9,80 | initSpeed:0,00 | Direction:true
y:490 | t:10,00 | initSpeed:0,00 | Direction:true
y:484 | t:0,20 | initSpeed:31,30 | Direction:false
y:478 | t:0,40 | initSpeed:31,30 | Direction:false
y:473 | t:0,60 | initSpeed:31,30 | Direction:false
y:468 | t:0,80 | initSpeed:31,30 | Direction:false
y:464 | t:1,00 | initSpeed:31,30 | Direction:false
y:459 | t:1,20 | initSpeed:31,30 | Direction:false
y:456 | t:1,40 | initSpeed:31,30 | Direction:false
y:452 | t:1,60 | initSpeed:31,30 | Direction:false
y:450 | t:1,80 | initSpeed:31,30 | Direction:false
y:447 | t:2,00 | initSpeed:31,30 | Direction:false
y:445 | t:2,20 | initSpeed:31,30 | Direction:false
y:443 | t:2,40 | initSpeed:31,30 | Direction:false
y:442 | t:2,60 | initSpeed:31,30 | Direction:false
y:441 | t:2,80 | initSpeed:31,30 | Direction:false
y:440 | t:3,00 | initSpeed:31,30 | Direction:false
y:440 | t:0,00 | initSpeed:31,30 | Direction:true
y:440 | t:0,20 | initSpeed:31,30 | Direction:true
y:441 | t:0,40 | initSpeed:31,30 | Direction:true
y:442 | t:0,60 | initSpeed:31,30 | Direction:true
y:443 | t:0,80 | initSpeed:31,30 | Direction:true
y:445 | t:1,00 | initSpeed:31,30 | Direction:true
y:447 | t:1,20 | initSpeed:31,30 | Direction:true
y:450 | t:1,40 | initSpeed:31,30 | Direction:true
y:453 | t:1,60 | initSpeed:31,30 | Direction:true
y:456 | t:1,80 | initSpeed:31,30 | Direction:true
y:460 | t:2,00 | initSpeed:31,30 | Direction:true
y:464 | t:2,20 | initSpeed:31,30 | Direction:true
y:468 | t:2,40 | initSpeed:31,30 | Direction:true
y:473 | t:2,60 | initSpeed:31,30 | Direction:true
y:478 | t:2,80 | initSpeed:31,30 | Direction:true
y:484 | t:3,00 | initSpeed:31,30 | Direction:true
y:490 | t:3,20 | initSpeed:31,30 | Direction:true
y:488 | t:0,20 | initSpeed:10,00 | Direction:false
y:487 | t:0,40 | initSpeed:10,00 | Direction:false
y:486 | t:0,60 | initSpeed:10,00 | Direction:false
y:485 | t:0,80 | initSpeed:10,00 | Direction:false
y:485 | t:0,00 | initSpeed:10,00 | Direction:true
y:485 | t:0,20 | initSpeed:10,00 | Direction:true
y:486 | t:0,40 | initSpeed:10,00 | Direction:true
y:487 | t:0,60 | initSpeed:10,00 | Direction:true
y:488 | t:0,80 | initSpeed:10,00 | Direction:true
y:490 | t:1,00 | initSpeed:10,00 | Direction:true
y:490 | t:0,00 | initSpeed:3,16 | Direction:true
y:490 | t:0,00 | initSpeed:0,00 | Direction:true
y:490 | t:0,00 | initSpeed:0,00 | Direction:true
y:490 | t:0,00 | initSpeed:0,00 | Direction:true
y:490 | t:0,00 | initSpeed:0,00 | Direction:true
y:490 | t:0,00 | initSpeed:0,00 | Direction:true
(Sollten die Variablen geändert werden, muss darauf geachtet werden, dass die for-Schleife hinreichend oft durchlaufen wird, damit die Ausgabe nicht "abgeschnitten" wird. Der Einfachheit halber habe ich auf einen Mechanismus hierbei verzichtet)
Markus.