Webworker
Phaser ist ein kostenloses JavaScript-Framework für HTML5-Spiele auf Basis von Canvas oder WebGL. Damit können Sie eigene 2D-Spiele entwickeln, sowohl für Desktop als auch für Mobile.
Eigene Spiele mit HTML 5 und Phaser entwickeln
W er in die Welt der Spieleentwicklung hineinschnuppern möchte, hat die Qual der Wahl. Es gibt Dutzende von Game Engines, mit verschiedenen Lizenz-Modellen und unterschiedlichen Schwerpunkten. Zu den bekanntesten zählen Unity, Unreal, GameMaker, Godot und Cry Engine. Wenn Sie bereits in JavaScript programmiert haben, ist Phaser einen Blick wert ( phaser.io). Mit diesem Framework entwickeln Sie 2DSpiele mit HTML5 für Desktop und Mobile. Es bietet alles, was Sie von einer modernen Game Engine erwarten können und ist zudem auch noch Open Source. Wir entwickeln mit Phaser in mehreren Teilen ein kleines Spiel namens Space Rush, bei dem der Spieler in einer bestimmten Zeit das Ziel erreichen muss. In diesem ersten Teil begnügen wir uns erst einmal damit, mit einem Quadrat über Plattformen zu springen.
Vorbereitung
Die aktuelle Version ist Phaser 3.24.1. Sie können das Framework unter phaser.io/ download/stable herunterladen, per npm installieren oder über ein CDN einbinden:
Für die Entwicklung benötigen Sie außerdem einen Webserver wie XAMPP ( apachefriends.org). Das mag auf den ersten Blick etwas überraschend sein; schließlich können Sie viele andere JavaScript-Bibliotheken lokal direkt und ohne Webserver ausprobieren. Bei Phaser werden Sie aber viele Assets einbinden – etwa Bilder, AudioFiles und JSON-Dateien. Browser erlauben
aus Sicherheitsgründen keinen Zugriff auf lokale Dateien. Sie wollen schließlich nicht, dass irgendein JavaScript beliebige Dateien auf Ihrem Rechner auslesen kann ( bit.ly/2RgZlLG). Sie benötigen daher einen Webserver und entwickeln das Spiel in einem entsprechenden Ordner innerhalb des Webservers; bei XAMPP zum Beispiel unter /xampp/htdocs/phaser. Innerhalb dieses Ordners arbeiten wir mit drei Dateien und einem Ordner für die Assets: /assets index.html main.js phaser.min.js
Sie können sich alle nötigen Dateien unter bit.ly/space-rush herunterladen. Das Paket beinhaltet zwei vorbereitete Ordner. Der eine enthält leere Dateien, in denen Sie selbst programmieren können; der andere enthält den nalen Stand dieses Artikels.
In den Ordner /assets kommen alle Dateien für animierte Sprites, statische Gra ken, Musik oder Sound-Effekte. Die phaser.min. js ist die aktuelle Version von Phaser. In der main.js entwickeln wir unser Spiel.
HTML-Gerüst & Phaser-Kon guration
Für die index.html genügen ein paar Zeilen:
Als nächstes kümmern wir uns um eine grundsätzliche Kon guration für Phaser. Schreiben Sie in die main.js: var config = { type: Phaser.AUTO, width: 800, height: 640, physics: { default: "arcade", arcade: { gravity: { y: 400 },
}
}, scene: { preload: preload, create: create, update: update
}
}; var game = new Phaser.Game(config); function preload () {} function create () {} function update () {}
Die Variable con g enthält Daten für die Kon guration. Der type legt fest, wie das Spiel gerendert wird. Erlaubte Werte sind Phaser.CANVAS, Phaser.WEBGL oder Phaser.AUTO. Der empfohlene Wert ist Phaser.AUTO. Phaser wird dann versuchen, das Spiel mit WebGL zu rendern. Wenn das nicht möglich ist, nutzt Phaser stattdessen ein canvas-Element.
Traditionell nutzen Spiele als Basis für gra sche Elemente oft 16 × 16, 32 × 32 oder auch 64 × 64 Pixel. Für Space Rush wählen wir 32 × 32 Pixel. Eine Breite und Höhe von 800 × 640 Pixel entspricht also einem Raster von 25 × 20 Einheiten.
Viele Spiele benötigen eine Physics Engine, die für die Simulation physikalischer Prozesse zuständig ist. Sie kümmert sich etwa um die Gravitation und klärt, ob Objekte zusammenstoßen und sich gegenseitig verschieben oder aufhalten. Phaser beinhaltet drei verschiedene Physics Engines: Arcade, Matter und Impact. Für unsere Zwecke eignet sich Arcade am besten. Diese Engine erlaubt nur rechteckige und runde Formen (geneigte Rechtecke sind nicht möglich).
Das schränkt zwar die möglichen Formen und Kollisionen ein, reicht aber für übliche Jump’n’Run-Spiele. Kollisionsabfragen lassen sich dadurch sehr einfach umsetzen und laufen performant ab. Wir sehen hier gleich einen Wert für die Gravitation vor. Bewegliche Objekte fallen dadurch in yRichtung, also nach unten.
Phaser arbeitet mit einem Scene Manager. Damit können Sie Ihr Spiel in sinnvolle Abschnitte unterteilen. So könnte es in einem Spiel verschiedene Szenen geben für: Titelbildschirm, das eigentliche Spiel, Credits sowie Screens für Game Over und Game Won. Unser Spiel besteht vorerst nur aus einer einzigen Szene. Für jede Szene sieht Phaser drei Funktionen vor: preload, create und update. In preload werden die benötigten Assets geladen, in create bereiten Sie mit diesen Assets Ihre Spielwelt vor, indem zum Beispiel Hintergrundgra ken, Plattformen und Sprites für den Spieler und Gegner eingesetzt werden. Die Funktion update wird immer wieder neu aufgerufen. In der Regel 60 mal pro Sekunde; es sei denn, das Spiel ist so umfangreich, dass die Performance leidet. Hier werten Sie insbesondere den Spielerinput über Keyboard oder Gamepad aus und reagieren darauf. Füllen wir diese Funktionen mit Leben.
Die preload-Funktion
Für den ersten Teil begnügen wir uns mit drei Assets: einem Hintergrund, den Plattformen und einem Sprite für den Spieler. Über this.load.image können wir die jeweiligen Gra ken laden. Das erste Argument ist der Name, mit dem wir die Gra k danach in Phaser ansprechen können, das zweite Argument ist der Pfad zu der Gra k. function preload () { this.load.image("background",
"assets/background.png"); this.load.image("platform",
"assets/platform.png"); this.load.image("square",
"assets/square.png"); }
Die Gra ken sind so angelegt, dass Sie in das Raster von 32 × 32 Pixel passen. Die Hintergrundgra k entspricht der Größe des Spiels: 800 × 640 Pixel. Eine einzelne Plattform ist 192 × 32 Pixel groß. Die Spiel gur ist für den Moment nur ein 32 × 32 Pixel großes Quadrat mit einem Gesicht.
Die create-Funktion
Nun setzen wir die vorbereiteten Assets in die Spielwelt ein. Ersetzen Sie die leere create-Funktion durch: function create () { this.add.image(400, 320, "background"); platforms =
this.physics.add.staticGroup(); platforms.create(128, 592, "platform"); platforms.create(320, 400, "platform"); platforms.create(640, 336, "platform"); player = this.physics.add.sprite (64,
320, "square"); player.setBounce(0.4); this.physics.add.collider(player,
platforms); cursors = this.input.keyboard.createCursorKeys(); }
Zunächst setzen wir das Hintergrundbild bei den Koordinaten 400, 320 ein. In Phaser gelten diese Koordinaten für den Mittelpunkt der jeweiligen Gra k.
Nun ergänzen wir eine sogenannte staticGroup namens platforms. Gruppen sind generell sinnvoll, weil sie die Kollisionsabfragen vereinfachen. Statt alle Kollisionen zwischen dem Spieler und den drei Plattformen einzeln abzufragen, packen wir die drei Plattformen in eine Gruppe und benötigen später nur eine Abfrage zwischen Spieler und Gruppe. Wir fügen hier also die Gra k platform an drei verschiedenen Positionen der Gruppe platforms hinzu. Eine staticGroup wird nicht von der Gravitation beein usst – andernfalls würden die Plattformen sofort nach unten aus dem Bildschirm fallen.
Nun fügen wir den Spieler player als Sprite ein. Im Gegensatz zu der staticGroup wirkt bei einem Sprite die Schwerkraft. Der player startet etwas oberhalb einer Plattform und fällt nach unten. Durch player. setBounce(0.4) geben wir dem Spieler ein leichtes Abprallen mit, wenn er auf dem Boden aufschlägt.
Für die Kollisionsabfrage zwischen Spieler und Plattformen reicht die Zeile this.physics.add.collider(player,platforms). Phaser überprüft dann immer wieder neu, ob sich Spieler und Plattformen berühren und sorgt dafür, dass sie sich nicht überlappen. Effektiv bleibt das Sprite dadurch auf Elementen der staticGroup stehen.
Zum Schluss bereiten wir noch die Eingabe über das Keyboard vor. Alle Tastendrücke landen in der Variablen cursors, auf die wir im nächsten Schritt reagieren können.
Die Update-Funktion
Das Spiel soll mit den Pfeiltasten gesteuert werden. Drückt der Spieler den Pfeil nach links oder rechts, erhält der player eine Geschwindigkeit in diese Richtung. Wird gerade keiner dieser beiden Pfeile gedrückt, stoppen wir die Bewegung in x-Richtung. Wenn der Pfeil nach oben gedrückt wird, soll der player eine Geschwindigkeit nach oben bekommen. Das soll aber nur dann passieren, wenn der player gerade auf einer Plattform steht ( player.body.touching. down). Andernfalls könnte er auch in der Luft springen und würde effektiv iegen. Um die Verrechnung der Geschwindigkeit in y-Richtung mit der Gravitation kümmert sich die Physics Engine automatisch. function update () { if (cursors.left.isDown) { player.setVelocityX(-160); player.flipX = true; } else if (cursors.right.isDown) { player.setVelocityX(160); player.flipX = false;
} else {
player.setVelocityX(0); } if (cursors.up.isDown && player.body.touching.down) { player.setVelocityY(-400); }
Abhängig von den gedrückten Tasten ändern wir hier lediglich ein paar Werte, die zum Sprite gehören. Diese Werte stehen in
Phaser automatisch bei Sprites zur Verfügung. Mit setVelocityX, setVelocityY legen Sie Geschwindigkeiten fest. Über ipX können Sie das Sprite spiegeln.
Um das Spiel lokal zu testen, müssen sich die Dateien in einem Ordner des Webservers be nden, und der Webserver muss gestartet worden sein.
Aktuell ist das alles noch recht rudimentär. Sie können mit der Spiel gur über die Plattformen hüpfen. Dabei könnten Sie unten aus dem Bildschirm fallen; dann geht es nicht weiter. Im nächsten Teil bauen wir die Spielwelt aus und sorgen dafür, dass die Spiel gur animiert wird.