Spielplatz
3D-Welten mit Python und Panda3D
Kamera
Die folgenden vier Zeilen legen schließlich fest, dass sich beim Drücken der Cursortasten die Kamera bewegt. Die Links- und Rechts-Taste führen die Methode spinCamera() aus, die Oben- und Unten-Tasten zoomCamera(). Bei der Zuweisung dieser Funktionen durch accept() kann eine Liste weiterer Parameter folgen, die Panda der verknüpften Funktion übergibt.
In Listing 2 bekommen die Kamerafunktionen als einzigen Parameter die Richtung der Kamerabewegung übergeben (1 und -1), die Listennotation mit den eckigen Klammern muss aber trotzdem eingehalten werden. Die vorletzte Anweisung der Init-Methode schaltet die automatische Kamerabewegung ab (disableMouse()). Die letzte setzt über das Kameraobjektiv-Objekt base.camLens die Ebene, ab der Panda3D Objekte ausblendet (Clipping Plane), auf den Wert 10000. Über dasselbe Objekt ließe sich beispielsweise auch die Brennweite des Objektivs verändern.
Die Funktionen, die die Kamera bewegen und rotieren, sind recht einfach aufgebaut. Winkel (angle) und Abstand (distance) werden mit einem festen Faktor multipliziert und dann, je nach Richtung, zum aktuellen Wert addiert oder von ihm abgezogen. Den resultierenden Wert weisen die Kamera-Methoden setHpr() respektive setPos() (Position) der Default-Kamera zu, die sich über base.camera auch in eigenen Skripts ansprechen lässt.
Bewegen
Im letzten Beispiel bewegte sich zwar die Kamera rund um den dargestellten Pandabären, das Tier selbst stand aber still. Für etwas mehr Action gibt es zwei Optionen, die sich optimal ergänzen: ein Bewegungsablauf des Modells selbst und seine Bewegung im Raum.
Eigene Bewegungen wie Laufen, Springen etc. legen Sie am besten in einem 3D-Modeller wie Blender fest. Dort designen Sie alle Bewegungsphasen und versehen das Modell dafür mit so genannten Armatures, die man sich wie die Knochen eines Lebewesens vorstellen kann. Ähnlich wie bei Marionetten lassen sich die Modelle dann über einzelne Bewegungspunkte animieren.
Haben Sie solche Sequenzen mit dem Chicken-Plugin exportiert, laden Sie die Bewegungsphasen zusätzlich zum Grundmodell. Panda3d bietet dafür die Klasse Actor, die sich im Wesentlichen verhält wie ein normales Modell, aber eben auch Bewegungsphasen verarbeitet. Listing 3 zeigt einen Ausschnitt aus einem Programm, das davon Gebrauch macht.
Listing 3
def __init__(self):
self.panda = Actor.Actor("models/panda-model", {"walk":"models/panda-walk4"})
…
self.panda.reparentTo(render)
…
self.accept('a', self.animate_start)
self.accept('s', self.animate_stop)
…
def animate_start(self):
self.panda.loop("walk")
def animate_stop(self):
self.panda.stop()
Hinter dem ersten Parameter der Actor-Methode, der das Grundmodell angibt, folgt als zweiter ein Python-Dictionary, dessen Schlüssel die Bewegungsphase spezifizieren (walk), dessen Werte widerum die entsprechenden Modellsequenzen (models/panda-walk4). Danach lässt sich die Animation mit der Methode loop() starten und unendlich lange wiederholen (Zeile 12). Die Funktion stop() beendet die Bewegung wieder. Im Beispiel binden die Zeilen 7 und 8 die Tasten [A] und [S] dazu an die entsprechenden Funktionen.
Die Bewegung im Raum lässt sich durch die bereits vorgestellte Funktion setPos() realisieren, Panda bietet aber noch eine weitaus leistungsfähigere Möglichkeit, so genannten Intervalle. Sie ermöglichen, einfach nur Start- und Endwerte sowie Dauer von Animationen festzulegen (also Position etc.). Die Berechung der Zwischenwerte übernimmt dann Panda3D. Listing 4 demonstriert, wie man ein Intervall verwendet, um das geladene Modell einmal um die eigene Achse zu drehen.
Listing 4
def rotate(self):
hprInterval = self.panda.hprInterval(4, Point3(360,0,0), startHpr=Point3(0,0,0))
hprInterval.start()
def createmenu(self):
text = OnscreenText(text = 'a: animate, s: stop, r: rotate, esc: exit', pos
= (-0.8, 0.9), scale = 0.07)
Der erste Parameter der Methode hprInterval legt in Sekunden fest, wie lange die Bewegung dauern soll. Danach folgen erst der Endpunkt und dann der Startpunkt der Bewegung, in diesem Fall der Rotationswinkel von 360 Grad. Zusätzlich zeigt Listing 4 in der Funktion createmenu() wie man mit nur einer Zeile einen kurzen Hilfetext einblendet (Abbildung 4).
Ein anderes Feature, mit dem Panda3D dem Programmierer Arbeit abnimmt, ist der so genannte Task. Beliebige solche Aufgaben führt die Engine aus, wenn man sie beim so globalen Task-Manager-Objekt taskMgr registriert. Dabei kann die Arbeit entweder sofort ausgeführt oder, bei größerem Aufwand, mit der Methode doMethodLater() auf später verschoben werden.
Viele weitere Fähigkeiten der Panda-Engine sollen hier nur kurz Erwähnung finden, denn jede für sich ist schon einigermaßen komplex. So bietet Panda Grundfunktionen für Kollisionserkennung, die verhindert, dass sich 3D-Modelle auf dem Bildschirm unrealistisch überschneiden.
Sogar eine eigene Physik-Engine bringt Panda mit. Sie bildet die Grundlage für das realistische Verhalten von Objekten, verleiht ihnen beispielsweise Masse, die sich entsprechende der (einstellbaren) Schwerkraft verhält. Auch GUI-Funktionen, mit denen sich in Spielen Menüs aufbauen lassen, fehlen nicht. Die heute so populären Shader beherrscht Panda3D ebenfalls, allerdings bisher nur in der Nvidia-Shadersprache Cg und nicht etwa im OpenGL-Standard GLSL.
Der letzte Wermutstropfen für Freunde freier Software ist schließlich die eingebaute Soundengine. Hier setzt Panda3D auf FMOD, das nicht unter einer freien Lizenz steht. Weil sich Panda3D dank Python aber gut mit anderen Frameworks versteht, lässt sich die Soundfunktion zum Beispiel durch das freie Paket Pygame ersetzen.



