api:documentation:grafik:animation
Unterschiede
Hier werden die Unterschiede zwischen zwei Versionen angezeigt.
— | api:documentation:grafik:animation [2024/08/31 12:03] (aktuell) – angelegt - Externe Bearbeitung 127.0.0.1 | ||
---|---|---|---|
Zeile 1: | Zeile 1: | ||
+ | ====== Animation von Grafikobjekten (die act-Methode) ====== | ||
+ | <WRAP center round info 100%> | ||
+ | Alle modernen Game-[[https:// | ||
+ | Auch in unserer Programmier-API gibt es diese Game-Loop. Sie wird 30-mal pro Sekunde aufgerufen und ruft ihrerseits die Update-Methode aller Spielobjekte auf, genauer: Diese Methode heißt '' | ||
+ | Wenn wir also eine Klasse schreiben, die von einer Grafikklasse (oder direct von der Klasse '' | ||
+ | Klingt kompliziert? | ||
+ | </ | ||
+ | |||
+ | < | ||
+ | <div style=" | ||
+ | </ | ||
+ | ===== Beispiel 1: Drehendes Rechteck ===== | ||
+ | * Starte das Programm und regle die Geschwindigkeit hoch/ | ||
+ | * Die Bewegung des Rechtecks ist sehr weich (ohne Ruckeln), da die '' | ||
+ | < | ||
+ | <div class=" | ||
+ | <script type=" | ||
+ | new World(1000, 1000); | ||
+ | new RotatingRectangle(300, | ||
+ | // Sobald ein Programm eine act-Methode überschreibt, | ||
+ | // Hauptprogramms mit der Ausführung nicht abbrechen darf, sondern regelmäßig die act-Methoden aufrufen | ||
+ | // muss. Die folgende Zeile ist daher unnötig. | ||
+ | // | ||
+ | |||
+ | class RotatingRectangle extends Rectangle { | ||
+ | |||
+ | | ||
+ | rotate(2); | ||
+ | } | ||
+ | |||
+ | } | ||
+ | </ | ||
+ | </ | ||
+ | </ | ||
+ | |||
+ | ===== Beispiel 2: Hin- und herbewegende Rechtecke ===== | ||
+ | * Das '' | ||
+ | < | ||
+ | <div class=" | ||
+ | <script type=" | ||
+ | new World(1000, 1000); | ||
+ | |||
+ | for(int i = 0; i < 10; i++){ | ||
+ | new MovingRectangle(100*i); | ||
+ | } | ||
+ | |||
+ | class MovingRectangle extends Rectangle { | ||
+ | |||
+ | int dx = -8; | ||
+ | |||
+ | | ||
+ | super(Math.random()*800 + 100, y, 80, 80); | ||
+ | setFillColor(Color.lightcyan); | ||
+ | } | ||
+ | |||
+ | | ||
+ | move(dx, 0); | ||
+ | if(getCenterX() < 100) { | ||
+ | dx = 8; // Umkehren am linken Rand | ||
+ | } else if(getCenterX() > 900) { | ||
+ | dx = -8; // Umkehren am rechten Rand | ||
+ | } | ||
+ | } | ||
+ | |||
+ | }</ | ||
+ | </ | ||
+ | </ | ||
+ | |||
+ | ===== Beispiel 3: Fliegende Bälle ===== | ||
+ | Jetzt wird's Zeit für ein anspruchsvolleres Beispiel: Wir wollen Bälle simulieren, die vom der Mitte des unteren Bildschirmrandes aus hochgeworfen werden und sich unter dem Einfluss der Gravitationskraft möglichst " | ||
+ | $$v_{x, neu} = v_x$$ | ||
+ | $$v_{y, neu} = v_y - g\cdot\Delta t$$ | ||
+ | $$x_{neu} = x + v_{x, neu}\cdot\Delta t$$ | ||
+ | $$y_{neu} = y + v_{y, neu}\cdot\Delta t$$ | ||
+ | Das $g$ in der zweiten Gleichung ist die Erdbeschleunigung $g = 9, | ||
+ | Als Spieleprogrammierer wollen wir natürlich, dass der Algorithmus möglichst schnell abläuft. Wir setzen daher $$\Delta t = 1 s$$ und passen dafür die Anfangsgeschwindigkeit und die Beschleunigung etwas an. Da sich $v_x$ nicht ändert, ist bei jedem Zeitschritt also nur noch folgendes zu tun: | ||
+ | $$v_{y, neu} = v_y + g$$ | ||
+ | $$x_{neu} = x + v_x$$ | ||
+ | $$y_{neu} = y + v_{y, neu}$$ | ||
+ | Als Physiklehrer überfällt mich ein großes Unbehagen, wenn ich an die Einheiten der drei obigen Gleichungen denke. Stellt Euch daher rechts jeweils " | ||
+ | === Erzeuger-Objekt === | ||
+ | Im [[# | ||
+ | |||
+ | < | ||
+ | <div class=" | ||
+ | <script type=" | ||
+ | new World(800, 1000); | ||
+ | new Erzeuger(); | ||
+ | |||
+ | class Erzeuger extends Actor { | ||
+ | int zähler = 0; | ||
+ | | ||
+ | zähler++; | ||
+ | if(zähler == 5) { // Jede 1/6-Sekunde (5 * 1/30 = 1/6) wird... | ||
+ | new FliegenderBall(); | ||
+ | | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | |||
+ | class FliegenderBall extends Circle { | ||
+ | |||
+ | | ||
+ | | ||
+ | |||
+ | | ||
+ | super(400, 950, 20); // Kreis mit Radius 20 und Mittelpunkt bei (400;950) | ||
+ | setFillColor(Math.floor(Math.random() * 0xffffff)); | ||
+ | } | ||
+ | |||
+ | | ||
+ | vy += 0.2; // Die Gravitation beeinflusst die y-Geschwindigkeit (N.B.: y-Achse zeigt nach unten!) | ||
+ | move(vx, vy); // Methode der kleinen Schritte! | ||
+ | if(isOutsideView() && getCenterY() > 500) { | ||
+ | | ||
+ | } | ||
+ | } | ||
+ | |||
+ | } | ||
+ | </ | ||
+ | </ | ||
+ | </ | ||
+ | |||
+ | ===== Beispiel 4: Feuerwerk ===== | ||
+ | Dieses Beispiel habe ich als Wiederholungsübung für meine zehnten Klassen im Schuljahr 2020/21 geschrieben. Damals war wegen er Corona-Epidemie das Sylvesterfeuerwerk ausgefallen. | ||
+ | {{ youtube> | ||
+ | < | ||
+ | <div class=" | ||
+ | <script type=" | ||
+ | new Feuerwerk(); | ||
+ | |||
+ | class Feuerwerk extends Actor { | ||
+ | |||
+ | | ||
+ | if(Math.random() < 0.03) { | ||
+ | |||
+ | int funkenzahl = Math.floor(Math.random() * 50 + 30); | ||
+ | int farbe = Color.randomColor(128); | ||
+ | |||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | new Funke(x, y, farbe, lebensdauer); | ||
+ | } | ||
+ | | ||
+ | |||
+ | } | ||
+ | } | ||
+ | |||
+ | } | ||
+ | |||
+ | class Funke extends Circle { | ||
+ | | ||
+ | | ||
+ | | ||
+ | |||
+ | | ||
+ | super(x, y, 4); | ||
+ | double winkel = Math.random() * 2 * Math.PI; | ||
+ | double v = Math.random() * 15 + 5; | ||
+ | vx = v * Math.cos(winkel); | ||
+ | vy = v * Math.sin(winkel); | ||
+ | setFillColor(farbe); | ||
+ | this.lebensdauer = lebensdauer; | ||
+ | } | ||
+ | |||
+ | | ||
+ | lebensdauer--; | ||
+ | move(vx, vy); | ||
+ | vy = vy + 0.2; | ||
+ | if(lebensdauer < 30) { | ||
+ | | ||
+ | } | ||
+ | if(isOutsideView() || lebensdauer < 0) { | ||
+ | | ||
+ | } | ||
+ | } | ||
+ | |||
+ | } | ||
+ | </ | ||
+ | </ | ||
+ | </ | ||
api/documentation/grafik/animation.txt · Zuletzt geändert: 2024/08/31 12:03 von 127.0.0.1