EINFÜHRUNG |
Die Computergrafik wird vielfach zur Darstellung von zeitlich veränderlichen Inhalten verwendet. Damit kannst du einen Ablauf in der Physik oder Biologie simulieren oder ein Computergame erstellen. Man nennt ein solches Programm allgemein eine Animation. Um den zeitlichen Ablauf sichtbar zu machen, wird immer nach einem gleich grossen Zeitschritt, den man Animationsschritt nennt, ein neues Bild gezeichnet. |
VERÄNDERUNG GLOBALER VARIABLEN |
Es ist üblich, im Hauptprogramm eine endlose Animationsschleife einzuführen, die step() immer wieder aufruft. Durch Einbau einer Verzögerung, kann man die Geschwindigkeit der Animation verändern. In step() soll die globale Variable t in jedem Schritt erhöht und beim Erreichen von 2P wieder auf Null gesetzt und die Farbe verändert werden. import math from gpanel import * def step(): global t x = r * math.cos(t) y = r * math.sin(t) t = t + 0.1 if t > 6.28: t = 0 setColor(getRandomX11Color()) move(x, y) fillCircle(10) makeGPanel(-500, 500, -500, 500) bgColor("darkgreen") t = 0 r = 200 while True: step() delay(10) |
MEMO |
Python verbietet, in Funktionen den Wert von globalen Variablen zu verändern. Wir können dieses Verbot aber umgehen, indem wir in der Funktion die Variable mit dem Schlüsselwort global versehen. Der Bezeichner global birgt Gefahren: Jede beliebige Funktion kann nicht nur eine als global bezeichnete Variable verändern, sondern sie sogar erzeugen, wie folgendes Beispiel zeigt: def set(): global a a = 2 def get(): print "a =", a set() get() Da set() eine Variable a erzeugt, die im ganzen Programm sichtbar ist, sagt man, dass die Funktion set() Nebenwirkungen (auch Seiteneffekte gennant) habe. Beachte auch, wie man elegant mit der print-Anweisung durch Kommatrennung mehrere Grössen hintereinander in die Console schreiben kann. Beim Ausschreiben wird das Komma durch einen Leerschlag ersetzt. |
DER TRICK MIT DEM EXAKTEN TICK |
Die Animationsschleife sollte in möglichst gleichen Zeitticks, d.h. mit der gewünschten Animationsperiode, durchlaufen werden, da sonst die Bewegung ruckelt. In step() wird jeweils der neue Animationszustand aufgebaut und dies kann unterschiedlich viel Zeit in Anspruch nehmen, da eventuell nicht immer gleiche Codeteile durchlaufen werden, aber auch deswegen, weil der Computer im Hintergrund noch mit anderen Aufgaben beschäftigt ist, was die Ausführung des Python-Codes verzögert. Um das verschieden lange dauernde step() auszugleichen, wird daher folgender Trick angewendet, auf den du auch selbst gekommen wärst: Man merkt sich in der Variable startTime vor dem Aufruf von step() die aktuelle Uhrzeit. Nach der Rückkehr von step() wartet man in einer Warteschleife so lange, bis die Differenz der neuen Uhrzeit und der Startzeit die Animationsperiode erreicht.
from gpanel import * import time def step(): global x global v clear() lineWidth(5) move(25, 300) rectangle(50, 100) move(575, 300) rectangle(50, 100) x = x + v image("_sprites/football.gif", x, 275) if x > 500 or x < 50: v = -v makeGPanel(0, 600, 0, 600) bgColor("forestgreen") enableRepaint(False) x = 300 v = 10 while True: startTime = time.clock() step() repaint() while (time.clock() - startTime) < 0.020: delay(1) |
MEMO |
Du kannst mit time.clock() die aktuelle Zeit als Dezimalzahl erhalten. Der erhaltene Wert ist zwar computerabhängig (Prozessorzeit oder Zeit seit dem ersten Aufruf von clock()). Da du aber nur die Zeitdifferenz benötigst, spielt dies keine Rolle. Du speicherst die Zeit vor dem Aufruf von step() und wartest am Ende der Animationsschleife mit einem delay(1) so lange, bis die Zeitdifferenz zwischen aktueller Zeit und Startzeit die Animationsperiode (in Sekunden) erreicht. Merke dir diesen Trick, denn du wirst ihn für viele Prozesse, die möglichst periodisch ablaufen sollen, anwenden. Im GPanel ist jeder Grafikbefehl im Bildschirmfenster sofort sichtbar. Das Löschen mit clear() bei Animationen zeigt daher auch kurzzeitig ein leeres Grafikfenster, was zu einem Flackereffekt führen kann. Um dies zu vermeiden, sollte bei Animationen die Doppelpufferung angewendet werden. Man erreicht dies durch den Befehl enableRepaint(False), der bewirkt, dass die Grafikbefehle nur noch in einem Hintergrund-Puffer (offscreen buffer) ausgeführt werden und nicht mehr automatisch im Grafikfenster sichtbar sind. Auch clear() löscht dann nur noch den Hintergrund-Puffer. Das Anzeigen des Grafikpuffers auf dem Bildschirm (Rendern genannt) musst du dann selbst im richtigen Moment durch Aufruf von repaint() auslösen. Auch in diesem Programm musst du in der Funktion step() die Variablen x und v mit global kennzeichnen, da sie in der Funktion verändert werden. |
AUFGABEN |
|