In Greenfoot 3 ein scrollendes Hintergrundbild anzulegen ist recht einfach, wenn man keine zu großen Ansprüche hat.

Hintergrundbild scrollen

Verwenden Sie für die folgenden Code-Vorschläge als Hintergrundbild für die Welt ein Bild, das wesentlich breiter ist als die Welt. Wenn also die Welt mit super(800, 400, 1) erzeugt wird (d.h.: 800 Pixel breit), dann nehmen Sie als Hintergrundbild eines, das 2000 Pixel oder breiter ist. Hier haben Sie eines zum Runterladen (Klick aufs Bild, 9000 x 400 Pixel):

Golden Gate Bridge Panorama (9000x400 Pixel)

Große Bilder (d.h.: große Ausmaße, große Dateigrößen) führen in Greenfoot 3 leicht mal zu ruckeligem Scrollen.

Die einfachste Möglichkeit besteht darin, in der act()-Methode der Welt die Zeile

this.getBackground().drawImage(this.getBackground(),-3,0)

einzufügen. Erklärung:

  1. this.getBackground() - holt den Hintergrund der Welt als GreenfootImage (siehe auch unten).
  2. drawImage(...) setzt auf dieses Hintergrundbild ein neues Bild. Die Methode drawImage(...) bekommt drei Parameter:
    • ein Bild vom Typ GreenfootImage. Wir verwenden einfach unser schon vorhandenes Hintergrundbild, siehe Punkt 1
    • einen x-Wert (= um wie viel Pixel wird das gezeichnete Bild nach rechts/links verschoben?). Mit -3 zeichnen wir das Bild um 3 Pixel nach links versetzt, so dass eine stillstehende Spielfigur den Eindruck erweckt, sich nach rechts zu bewegen. Passen Sie den Wert entsprechend an (z.B. -6 für höhere Geschwindigkeiten, -1 für langsamere). Je höher die Geschwindigkeit, desto eher ruckelt alles.
    • einen y-Wert. Da wir in y-Richtung keine Veränderung vornehmen wollen, nehmen wir 0. Wenn Sie einen Top-Down-Scroller fabrizieren wollen, setzen Sie x auf 0 und verändern den y-Wert. Dann müssen Sie aber auch ein hochformatiges Bild nehmen.

Hintergrundbild wiederholen

Irgendwann ist auch das breiteste Hintergrundbild zuende. Dann wollen wir, dass es wieder von vorne beginnt. Das wird nun etwas komplizierter.

Zuerst legen wir uns ein paar Attribute an (oben bei "Fields" die Taste v drücken):

private int bildbreite = this.getBackground().getWidth()
private int nichtSichtbarerBildbereich = this.bildbreite - this.getWidth()
private int rechterRandBild = this.bildbreite
private int geschwindigkeit = 4

Erklärung:

  • bildbreite - die Breite des Bilds in Pixeln. Dazu holen wir uns wieder den Hintergrund als GreenfootImage und verwenden die Methode getWidth(). Achtung! Wir erhalten so die Gesamtbreite des Bildes, also im Beispiel 9000 (weil das Bild 9000 Pixel breit ist). Wenn wir die Breite der Welt brauchen (also den sichtbaren Bereich), benutzen wir die World-Methode getWidth() (s.u.)
  • nichtSichtbarerBildbereich - Wenn die Welt 900 Pixel breit ist, das Bild aber 9.000 Pixel misst, dann sind 8.100 Pixel außerhalb des sichtbaren Bereichs. diesen Wert brauchen wir nachher. Wir ziehen also von der Bildbreite (s.o.) die Breite des sichtbaren Bereichs ab (this.getWidth(), wobei this die Welt ist).
  • rechterRandBild - Das Bild hat links die Position 0 (das ist der Standard- oder Defaultwert). Der rechte Rand des Bildes befindet sich also an einer x-Position, die der Bildbreite entspricht.
  • geschwindigkeit - Wir definieren, wie schnell der Hintergrund scrollen soll.

Als nächstes lagern wir die Befehle für das Scrollen in eine eigene Methode aus. Wir könnten das folgende auch in der act()-Methode schreiben. Allerdings würde der Code dadurch schnell unübersichtlich.

public void scrollen()
    this.getBackground().drawImage(this.getBackground(), -this.geschwindigkeit, 0)
    this.rechterRandBild = this.rechterRandBild - this.geschwindigkeit
    if(this.rechterRandBild <= this.bildbreite - this.getWidth())
        this.rechterRandBild = this.bildbreite
        this.getBackground().drawImage(this.getBackground(), this.bildbreite - this.getWidth(), 9)

Erklärung:

  • Die Methode heißt scrollen(). Wir rufen Sie in der act()-Methode mit this.scrollen() auf. Es wird also einmal pro act()-Zyklus gescrollt.
  • Wir verschieben (wie oben schon erklärt) das Bild etwas nach links, in diesem Fall um -this.geschwindigkeit. Wenn this.geschwindigkeit den Wert 4 hat, verschieben wir das Bild also um -4 nach links.
  • Der rechte Rand des Bildes (s.o.) hat sich nun auch entsprechend nach links verschoben. Wir aktualisieren diesen Wert.
  • Nun fragen wir ab, ob der rechte Rand des Bildes schon am rechten Rand der Welt/des Szenarios angekommen ist. (Wenn das Bild also 9.000 Pixel breit ist, das Szenario 900 Pixel, dann darf der rechte Rand nicht kleiner als 8.100 sein.) Ist das der Fall, müssen wir das Bild wieder in seine Ursprungsposition verschieben: Wir setzen rechterRandBild wieder auf seinen Ursprungswert und verschieben das Bild an seine Ursprungsposition (nämlich im Beispiel um 8.100 Pixel nach rechts).
Screenshot: Greenfoot 3 mit links-scrollendem Hintergrundbild

Übrigens wäre es schick, wenn wir nicht dauernd this.getBackground()... schreiben müssten. Warum holen wir uns nicht zu Beginn unserer Methode den Hintergrund als GreenfootImage? Dazu schreiben wir zu Beginn der Methode scrollen() einfach

var GreenfootImage hintergrund = this.getBackground().getImage

und ersetzen in der Methode alle this.getBackground()... durch hintergrund. Beachten Sie, dass wir hier KEIN this schreiben, weil es sich nicht um ein Attribut handelt (das wir oben bei "Fields" definieren würden und das für die ganze Klasse gültig wäre), sondern um eine lokale Variable.

Der ganze Code in Greenfoot 3 sieht dann so aus:

Screenshot Greenfoot 3: Hintergrundbild scrollen lassen

Unendlich scrollende Textur

Wenn Sie ein scrollendes Hintergrundbild in Greenfoot 3 haben, sind Sie in gewisser Weise unflexibel, da das Hintergrundbild eine gewisse Begrenzung hat. Besser läuft es da mit Texturen oder bspw. den Greenfoot-eigenen Mustern für den Hintergrund.

Allerdings ist das nicht ganz trivial; bis ich dazu komme, das hier zu erklären, ist das Greenfoot-Monster bereits im Ruhestand. Wenn Sie es unbedingt sofort brauchen, können Sie sich im Szenario Infinite Scrolling World kundig machen. Das, was Sie brauchen, steht in der Klasse ScrollingWorld und dort in der Methode createTextur(). Hier wird im Wesentlichen eine verschachtelte Schleife angelegt, die bei jedem Scrollschritt den Bildschirm von Neuem mit den Texturblöcken ("Tiles") füllt (möglicherweise kann man das auch wesentlich einfacher machen).