Tutorial: Physik
Inhaltsverzeichnis
Ziel
Nach erfolgreichem Abschluss dieses Tutorials kannst du die Physik-Funktionen der Engine nutzen.
Vorwort
Bis zur Version 2.x gab es in der Engine Alpha nur eine sehr einfache Physik. Ein Objekt war entweder aktiv oder passiv. Aktive Objekte unterliegen der Schwerkraft und können passive Objekte nicht durchdringen. Aktive Objekte können von passiven Objekten "mitgenommen" werden.
Ab Version 3.0 wurde zusätzlich eine Newton'sche Physik eingeführt, d.h. Objekte können eine Masse und einen Impuls haben. Auf sie können Kräfte oder Kraftstöße einwirken und es kommt zu Impuls-Übertrag. Auch Reibung ist realisiert. Die neuen Physik-Funktionen in der Engine sind noch in der Entwicklung. Eine frühe Testversion ist bereits in der Engine enthalten, jedoch gibt es noch Lücken und Inkonsistenzen in den Physik-Funktionen.
Die hier demonstrierten Funktionen und Demo-Projekte funktionieren in der aktuellsten Version (Nightly). Sollte ein Bug gefunden werden, freuen wir uns über dein Feedback!
Die API (also die Nutzungsweise der Funktionen) wird sich nicht ändern.
Prinzip der einfachen Physik
aktive, passive und neutrale Objekte
Die Klasse Raum
stellt für die einfache Physik zwei Möglichkeiten zur Verfügung:
public void aktivMachen()
Startet für dieses Objekt den einfachen Physik-Modus als aktives Objekt. Aktive Objekte werden von passiven Objekten aufgehalten und können sie nicht durchdringen.
public void passivMachen()
Startet für dieses Objekt den einfachen Physik-Modus als passives Objekt. Passive Objekte sind Böden, Wände, ... . Passive Objekte können aktive Objekte "mitnehmen" oder "wegschieben".
Mit der Methode
public void neutralMachen()
kann man den einfachen Physik-Modus eines Objekts wieder abgeschalten. Neutrale Objekte nehmen nicht an der Physik teil.
Schwerkraft
Für ein Objekt kann man die Schwerkraft einschalten mit der Methode:
public void schwerkraftAktivSetzen(boolean aktiv)
Man kann auch die Schwerkraft dosieren mit der Methode:
public void schwerkraftSetzen(int schwerkraft)
Der Standard-Wert für die Schwerkraft ist 4. Größere Werte führen zu einer schwächeren Fallbeschleunigung, kleinere Werte zu einer hefitgeren Fallbeschleunigung.
Springen
Ein Objekt kann springen mit der Methode:
public void sprung(int kraft)
Je stärker die Kraft, desto höher der Sprung. Nur aktive Objekte mit aktiver Schwerkraft können springen und auch das nur, wenn sie auf einem passiven Objekt stehen.
Stehen
Natürlich kann man überprüfen, ob ein aktives Objekt gerade steht (auf einem passiven Objekt) mit den Methoden:
public void steht()
und
public void stehtAuf(Raum r)
Es gibt auch ein Interface StehReagierbar
, das eine Methode public void stehReagieren()
vorschreibt. Ein Objekt einer Klasse, die dieses Interface implementiert, kann als Listener für eine Landung dienen. Soll etwas geschehen, wenn ein aktives Objekt nach einem Sprung wieder landet, dann muss das aktive Objekt bei einem StehReagierbar
-Objekt angemeldet werden. Hierzu gibt es in der Klasse Raum die Methode:
public void stehReagierbarAnmelden(StehReagierbar listener)
Zu tief gefallen
Es gibt auch ein Interface FallReagierbar
, das eine Methode public void fallReagieren()
vorschreibt. Ein Objekt einer Klasse, die dieses Interface implementiert, kann als Listener für zu tiefes Fallen dienen. Soll etwas geschehen, wenn ein aktives Objekt zu tief fällt, dann muss das aktive Objekt bei einem FallReagierbar
-Objekt angemeldet werden und eine kritische Tiefe angeben. Hierzu gibt es in der Klasse Raum
die Methoden:
public void fallReagierbarAnmelden(FallReagierbar listener, int kritischeTiefe)
und
public void kritischeTiefeSetzen(int kritischeTiefe)
Jedes aktive Objekt, das auf zu tiefes Fallen reagieren möchte, braucht exakt ein FallReagierbar
-Objekt, welches als sein Listener dient und in seiner Methode fallReagieren()
festlegt, was geschehen soll, wenn ein zu tiefer Fall des zu beobachtenden Objekts stattgefunden hat. Insbesondere sollte in dieser Methode das gefallene aktive Objekt wieder auf eine Höhe oberhalb der kritischen Höhe gehoben wird, da sonst die Methode fallreagieren()
unendlich oft aufgerufen würde.
Die Grundlagen: Newton'sche Physik
Bis einschließlich Version 3.x befindet sich die Newton'sche Physik in einem experimentellen Stadium! Es ist mit schwerwiegenden Bugs zu rechnen!
Dieses Kapitel nutzt einige mechanische Konzepte, so wie
- Geschwindigkeit / Masse
- Impuls
- Kräfte
und deren Zusammenhänge. Ein Grundwissen über deren Zusammenwirken ist sehr hilfreich für die Arbeit mit der Physik-Engine.
Ein gutes Modell für die meisten alltäglichen physikalischen, mechanischen Vorgänge ist die Newton'sche Mechanik. Diese wird auch in der Engine intern genutzt, um die physikalischen Vorgänge zu beschreiben, die während des Spiels geschehen.
Jedes Raum
-Objekt hat eine Reihe von Physik-Methoden, mit denen man die Physik-Funktionen der Engine nutzen kann. Die Methode newtonschMachen()
startet die Physik für ein Raum
-Objekt:
Raum raum; //Ein beliebiges Raum-Objekt, das instanziiert ist.
//Starte die Physik für das Raum-Objekt. Hiermit geht es los.
raum.newtonschMachen();
Nachdem ein Raum
-Objekt aktiviert wurde, kann man alle Physik-Methoden nutzen. Die Physik-Engine arbeitet intern mit den Standard-Einheiten der Physik. Hier ist eine Übersicht über die Methoden, die man an jedem (aktivierten) Raum
-Objekt ausführen kann:
Methode | Einheit (Parameter) | Funktionsweise |
---|---|---|
public void setzeMeterProPixel (
float mpp) |
Meter / Pixel
|
Durch die Pixel-Pro-Meter-Konstante kann die Engine die Standard-Einheit Meter auf die interne Einheit Pixel übertragen. Die Eingabe gilt für die gesamte Physik. Beispiel-Eingaben:
|
public void impulsHinzunehmen(
Vektor impuls) |
kg * (m / s)
|
Bewirkt einen Impuls-Übertrag auf das Objekt. Der Impuls sorgt (in der Regel) dafür, dass sich das Objekt bewegt. Beispiel-Eingabe:
|
public void geschwindigkeitHinzunehmen (
Vektor geschwindigkeit) |
m / s
|
Addiert zu der aktuellen Geschwindigkeit v_alt die Geschwindigkeit geschwindigkeit . Die neue Geschwindigkeit ist dann die Summe der beiden v_alt + geschwindigkeit .
Diese Funktion wirkt unabhängig von der Masse. |
public void luftwiderstandskoeffizientSetzen (
float luftwiderstandskoeffizient) |
N / ( (m/s) ^2 )
|
Setzt den sog. Luftwiderstandskoeffizienten für das Objekt in der Engine. Allgemein physikalisch ist der Luftwiderstands-Kraft eines Körpers F_w = 1/2 * [Dichte d. Luft] * c_w * [Querschnittsfläche] * v^2 .
Die Engine vereinfacht dies, indem alle Konstanten zu dem einen Luftwiderstandskoeffizienten zusammengefasst werden: |
public void masseSetzen (
float masse) |
kg
|
Setzt die Masse für dieses Objekt. Diese wird z.B. bei Kollisionen und anderen Impuls-Überträgen mit einbezogen. |
public void konstanteKraftSetzen (
Vektor kraft) |
N = kg * (m/s^2)
|
Setzt eine Kraft, die konstant auf das Objekt wirken soll. Beispiel:
|
public void geschwindigkeitSetzen (
Vektor geschwindigkeit) |
m / s
|
Setzt direkt eine neue Geschwindigkeit für dieses Objekt. Die alte Geschwindigkeit wird hierbei einfach ignoriert und überschrieben. |
public void einfluesseZuruecksetzen () |
* Setzt die konstant wirkende Kraft auf 0.
| |
public void kraftAnwenden (
Vektor kraft,
float t_kraftuebertrag) |
N = kg * m / s^2
|
Wendet die Kraft kraft innerhalb von t_kraftuebertrag Sekunden auf das Objekt an. Je schneller der Kraftübertrag (also je kürzer die Zeit), desto größer ist die Beschleunigung, die auf das Objekt wirkt.
|
public void beeinflussbarSetzen (
boolean beeinflussbar) |
Ist dieser Wert false , kann dieses Objekt durch Kollision mit anderen Physik-Objekten nicht verschoben werden. So kann man Wände/Decken/Plattformen etc. implementieren. Dieser Wert ist standardmäßig true .
|
Mit diesen Methoden kann man die kompletten Physik-Features abrufen.
Jump n' Run
Dieser Bereich wird erst ab Version 4.0 produktiv nutzbar sein, da die zugehörigen Features der Engine noch nicht ausgereift sind.
Probleme?
Du findest ein kleines Beispiel-Projekt, das ein einfaches Billiard-Projekt implementiert.