Klasse Sprite

Die hier verwendete Entwicklungsumgebung stellt verschiedene Grafiken zur Verfügung, die für Spiele oder Animationen verwendet werden können. Grafiken werden als Objekte der Klasse Sprite (engl. Bezeichnung für ein Geistwesen, Kobold) erzeugt.
Grafische Objekte wie Sprites werden dabei in einem Grafikfenster dargestellt, das 800 Pixel breit und 600 Pixel hoch ist. Der Ursprung liegt in der linken oberen Ecke des Fensters. Nach rechts verläuft die x-Achse, nach unten die y-Achse.

Wir deklarieren zunächst eine Variable mit dem Namen meinSprite vom Datentyp Sprite. Anschließend wird ein neues Sprite-Objekt erzeugt. Der Konstruktor erwartet vier Parameter:

Im Internet gibt es eine Übersicht über alle verfügbaren Grafiken für Sprites. Wir verwenden die Sammlung Space_Shooter_1 und wählen das Raumschiff mit der Nummer 2.

Das folgende Programm zeigt, wie der das Objekt der Klasse Sprite erzeugt wird und Methoden der Klasse verwendet werden können.

Verändere den Quelltext im oberen Fenster, so dass das Raumschiff von der linken oberen Ecke startet, waagrecht zum rechten Rand und anschließend senkrecht zum unteren Bildschirmrand fliegt.
meinSprite.moveTo(20, 20);
for(int i = 0; i < 140; i++) {
   meinSprite.move(5, 0); // Sprite um insgesamt 700px nach rechts bewegen
}
for(int i = 0; i < 110; i++) {
   meinSprite.move(0, 5); // Sprite um insgesamt 550px nach unten bewegen
}

Klasse Raumschiff

Klassenvererbung und Konstruktor

Ein Objekt der Klasse Sprite können wir zwar mit den vorhandenen Methoden der Klasse bewegen. Wir wollten unser Raumschiff aber mit weiteren Attributen, wie z. B. einem Namen für den Spieler oder einer Geschwindigkeit, und weiteren Methoden ausstatten.
Dazu nutzen wir das Prinzip der Vererbung, d.h. wir schreiben eine Klasse Raumschiff, die die Klasse Sprite erweitert.

Innerhalb des Konstruktors der Klasse Raumschiff muss mit der Methode super() der Konstruktor der Oberklasse Sprite aufgerufen werden. Als Parameter verwenden wir die gleichen wie oben. Das folgende Beispiel zeigt dies.

Ergänze den Quelltext im oberen Fenster, so dass die Klasse die im Klassendiagramm beschriebenen Attribute besitzt.

Der Konstruktor soll aus dem Parameter den Namen übernehmen und die x- und y-Position des Raumschiffs beim Aufruf von super() setzen.

Außerdem soll der Wert der Beschleunigung auf 0.2, die Geschwindigkeit in x-Richtung vx auf 0.3 und die Geschwindigkeit in y-Richtung vy auf 0.7 festgelegt werden.
Die Attribute vx und vy stehen dabei für die Geschwindigkeit des Raumschiffs in x- bzw. y-Richtung. beschleunigung beschreibt, wie stark das Raumschiff seine Geschwindigkeit ändert, wenn es später durch Tasten gesteuert wird.

class Raumschiff extends Sprite {
   // Attribute der Klasse Raumschiff 
   String name;
   double vx;
   double vy;
   double beschleunigung;

   Raumschiff(String name, double x, double y) {
      // Konstruktor der Klasse Sprite
      super(x, y, SpriteLibrary.Space_Shooter_1, 2);
      this.name = name;
      beschleunigung = 0.2;
      vx=0.3;
      vy=0.7;
   }
}
// Deklaration einer Variablen der Klasse Raumschiff
Raumschiff raumschiff1;
// Erzeugen eines Raumschiff-Objekts
raumschiff1 = new Raumschiff("Captain Kirk", 100, 50);

Die Methode act()

Unser Raumschiff soll durch Tasten in allen vier Bewegungsrichtungen zu steuern sein. Dazu nutzen wir die Methode act(), die die Klasse Sprite bereits besitzt. Diese Methode wird automatisch ca. 30 Mal in der Sekunde aufgerufen. In der Klasse Sprite ist der Methodenrumpf zunächst leer, eine erbende Klasse kann aber nun diese Methode überschreiben, d.h. sie wird in der Klasse Raumschiff noch einmal implementiert. Das folgende Beispiel zeigt das Verhalten der Methode act().

Verändere die Implementierung der Klasse, so dass bei jedem Aufruf der Methode act() das Raumschiff um vx nach rechts und um vy nach unten bewegt wird.

   void act() {
      move(vx, vy);
   }

Die Steuerung des Raumschiffes mit der Tastatur und der Einfluss der Schwerkraft

Bild von 2427999 auf Pixabay

Unser Raumschiff bewegt sich jetzt schon selbstständig bei gleich bleibender Geschwindigkeit in die beiden Raumrichtungen. Jedes Mal, wenn die Methode act() automatisch aufgerufen wird - und das passiert etwa 30 Mal pro Sekunde - wird das Raumschiff um vx nach rechts und um vy nach unten verschoben.

Die Steuerung funktioniert nun so, dass bei Drücken einer Taste (z. B. einer der vier Pfeiltasten) der Wert der Geschwindigkeit vergrößert bzw. verkleinert wird. Als Veränderung verwenden wir dabei den Wert des Attributs beschleunigung, also 0.2.

Dazu fragen wir innerhalb der Methode act() ab, ob eine der Tasten gerade gedrückt ist. Das folgende Beispiel zeigt dies für die linke Pfeiltaste.

Ergänze den Quelltext in der Methode act(), so dass die Geschwindigkeit des Raumschiffs auch beim Drücken der anderen drei Pfeiltasten entsprechend verändert wird.

      if(isKeyDown(Key.ArrowLeft)) {
         vx = vx - beschleunigung;
      }
      if(isKeyDown(Key.ArrowRight)) {
         vx = vx + beschleunigung;
      }
      if(isKeyDown(Key.ArrowUp)) {
         vy = vy - beschleunigung;
      }
      if(isKeyDown(Key.ArrowDown)) {
         vy = vy + beschleunigung;
      }

Es ist übrigens auch möglich, zwei Tasten gleichzeitig zu betätigen.

Wir sollten nun aber noch kontrollieren, dass unser Raumschiff nicht den sichtbaren Bereich verlässt. Die Klasse Sprite besitzt das Attribt centerX, das uns die momentane x-Koordinate des Raumschiffs verrät. Innerhalb der Methode act() sollte überprüft werden, ob die x-Koordinate nicht kleiner als 30 oder größer als 770 ist. Falls diese Werte unter- bzw. überschritten werden, sollte die x-Koordinate auf den Minimal- bzw. Maximalwert und vx auf 0 gesetzt werden. Wir bewegen das Raumschiff einfach wieder um -vx in horizontaler Richtung ein Stück zurück.

Für die linke Randbegrenzung erreicht man dies z. B. durch:

      if(centerX < 30) {
         move(-vx, 0);
         vx = 0;
      }

Die gleiche Korrektur ist notwendig, wenn das Raumschiff die x-Koordinate von 770 übersteigt.

Ergänze den Quelltext am Ende der Methode act() dementsprechend.

Lösung mit zwei if-Anweisungen:

      if(centerX < 30) {
         move(-vx, 0);
         vx = 0;
      } 
      if(centerX > 770) {
         move(-vx, 0);
         vx = 0;
      }

Das Problem kann auch mit nur einer if-Anweisung gelöst werden, bei der mit Hilfe des ||-Operators (ODER-Verknüpfung) gleichzeitig der minimale bzw. maximale x-Wert überprüft wird:

      if(centerX < 30 || centerX > 770) {
         move(-vx, 0);
         vx = 0;
      } 

Zu guter Letzt setzen wir das Raumschiff noch einer geringen Schwerkraft aus. Das heißt, dass das Raumschiff nach unten gleichmäßig beschleunigt werden soll. Beim Ausführen der act()-Methode addieren wir einen kleinen Wert, z. B. 0.05 zu vy. Dies bewirkt eine Beschleunigung nach unten.

      vy = vx + 0.05;
      move(vx, vy);

Ergänze den Quelltext in der Methode act() im letzten Programmfenster und teste das Verhalten des Raumschiffs.