Nachdem Sie in der Lage sind, Subklassen der Klasse CanvasElement zu erzeugen und diese anzeigen können, sollen diese Elemente nun animiert werden.
Hierzu sehen wir uns die dafür notwendigen Funktionsaufrufe an.
Hinweis: Im folgenden Klassendiagramm sind einige Properties und Methoden nicht aufgeführt, falls diese für diese Aufgabe unnötig sind.
Die abstrakte Klasse CanvasElement hat eine Methode animate(), welche als open deklariert ist und in den Subklassen überschrieben werden soll. In animate() werden alle Transformationen (Umwandlungen) oder Bewegungen eines CanvasElements implementiert.
Kreis erstellen
Die animate()-Funktion jedes an der EngineEmi registrieren CanvasElement-Objekts wird mehrmals pro Sekunde aufgerufen. Auf modernden Browsern teilweise deutlich öfter als 60 mal pro Sekunde (60FPS – Frames pro Sekunde).
Also können wir diese Funktion verwenden, um z.B. den Ort eines Objektes zu verändern. Die canvas, bzw. der context sind mit einem 2D-Koordinatensystem ausgestattet, welches in der linken oberen Ecke mit 0,0 beginnt. Der Punkt P(100,200) läge dann 100 Pixel nach rechts verschoben und 200 Pixel nach unten verschoben.
- Erstellen Sie eine Klasse AnimierterKreis und lassen Sie diese von Kreis erben (vergessen Sie nicht, die Kreis-Klasse der Engine zu importieren): import engineEmi.Kreis
- Implementieren Sie die einen geeigneten Konstruktor, der folgende Parameter übernimmt: x, y, farbe, radius
- Der durch die Vererbungshierarchie aufgerufene Superkonstruktor (von Kreis) soll die im vorigen Punkt angegeben Parameter übergeben bekommen und automatisch den context auf Engine.context setzen.
- Erzeugen Sie in der Datei Main.kt ein Objekt vom Typ AnimierterKreis nach der nebenstehenden Objektkarte
- Registrieren Sie dieses Objekt bei der Engine mit der Funktion .registerCanvasElement(CanvasElement) und testen Sie, ob der Kreis ordnungsgemäß angezeigt wird (Build & Run).
Kreis animieren
Nun kann der Kreis animiert werden, indem wir bei jedem Aufruf von animate() (man sagt „in jedem Frame“) die Koordinaten x und y verändern. Wir werden sie jedes mal um 1.0 erhöhen.
Hierzu öffnen Sie die Klasse AnimierterKreis und ergänzen Sie die Funktion animate() nach dem folgenden Schema:
In der Funktion animate() schreiben Sie hinter den Aufruf von super.animate() die folgenden Codezeilen:
x = x +1
Wir weisen also bei jedem Aufruf dem Attribut x den Wert x+1 zu. Hinweis: Als Kurzschreibweise kann man auch x++ verwenden.
Testen Sie Ihre Implementierung (Build & Run). Der Kreis sollte sich nun langsam nach rechts bewegen, bis er aus dem Canvas verschwindet. Hinweis: Das AnimierterKreis-Objekt selbst existiert immer noch. Es ist nur außerhalb der sichtbaren Canvas platziert.
2-Dimensionale Bewegung
Nun soll der Kreis entlang beider Achsen (also schräg) bewegt werden. Hierzu fügen Sie bitte die beiden Attribute deltaX und deltaY in der Klasse AnimierterKreis ein. Dies beiden Werte sollen jeweils in jedem Frame zu x und y addiert werden.
- Fügen Sie die beiden Attribute deltaX und deltaY in der Klasse AnimierterKreis ein
- Implementieren Sie die Addition dieser Werte zu x und y in der animate()-Funktion
- Wählen Sie für deltaX und für deltaY als Wert jeweils 1.0
Build & Run
Der Kreis bewegt sich nun schräg nach rechts unten, bis er aus der Canvas verschwindet.
Abprallen an den Canvas-Grenzen
An den Grenzen der Canvas soll der Ball ab jetzt physikalisch korrekt abprallen. An den Grenzen der Canvas drehen wir deltaX und deltaY einfach um, um das Abprallen zu simulieren.
Die Grenzen der Canvas sind für links und oben 0. Für rechts und unten sind die Grenzen die Breite und die Höhe der Canvas. Dieser erhalten wir mit:
val right = Engine.canvas.widt
val bottom = Engine.canvas.height
Falls jetzt die x die linke oder rechte Grenze überschreitet, drehen wir deltaX um
Falls jetzt die y die obere oder untere Grenze überschreitet, drehen wir deltaY um
Hierzu nutzen wir sogenannte bedingte Anweisungen (Conditionals). Hier ein Beispiel (In einem Video gibt es mehr zu Conditionals)
- Fügen Sie die folgenden Code-Zeilen an geeigneter Stelle ein
- Build & Run
val right = Engine.canvas.width
val bottom = Engine.canvas.height
if ((posX - this.width) < 0)
deltaX = deltaX*-1
if ((posX + this.width) > right)
deltaX = deltaX*-1
if ((posY - this.height) < 0)
deltaY = deltaY*-1
if ((posY + this.height) > bottom)
deltaY = deltaY*-1
Zusatzaufgabe
Erzeugen Sie mehr Bälle (AnimierterKreis-Objekte), welche sich in verschiedenen Richtungen und mit unterschiedlichen Geschwindigkeiten bewegen. Die Bälle sollen auch unterschiedliche Farben und Radien besitzen.