Intention
Viele Entwickler, die selber schon leidenschaftlich ein Spiel gezockt haben, träumen von der Umsetzung eigener Spieleideen.
Bei mir ist es hier nicht anders. Ich habe viele Ideen und viele davon sind unsinnig. Man würde sie vermutlich in die Kategorie „Trash“ stecken. Aber gerade professionell anmutende Spiele mit Trash-Faktor sind es, die viele Spieler fesseln. Die meisten Spiele, die nicht als „Trash“ gekennzeichnet sind, sind unter reellen Bedingungen absoluter Humbug.
Beispiele:
* Ein Klempner aus Brooklyn der Pilze frisst und auf Schildkröten rumtrampelt
* Eine Steinschleuder die kleine Vögel auf grüne Schweine schießt
* Prügelnde Kontrahenten, die Energiebälle schießen und mit Hubschrauberkicks durch die Gegend fliegen
* .. etc
Obwohl diese Spiele absolut unrealistisch sind, haben diese eine „Spielephysik“, die aber nicht unbedingt realisitsch sein muss.
* Super Mario springt und fällt auch wieder auf den Boden
* Ein Angry Bird schubst Teile seiner Welt an, diese stürzen um und schubsen wiederum weitere Teile an, solange bis das Schweinehaus zusammenfällt.
* Die Sequenz des Schießens bei Ryu/Ken benötigt eine gewisse Zeit in der sie angreifbar sind. Wenn Chun Li in der Luft ist kann Guile sie mit seinem Flip-Kick unbeschadet runterholen.
Distanziert betrachtet haben mich diese Spiele gefesselt und viel Zeit gekostet, waren aber konzeptuell absoluter Quatsch. Ob ich als Hobbyentwickler und Familienvater in meiner Frezeit die Zeit finde, an einem Spiel zu entwickeln, möchte ich an diesem Punkt noch bezweifeln aber ich lasse mich jetzt mal überraschen.
Aus diesem Grund wollte ich während meines Urlaubes den Einstieg in die HTML 5 Spieleentwicklung so hinbekommen, dass ich grundsätzlich ein 2D-Spieleentwicklungsproblem angehen kann.
Idee
Die erste Idee ist nichts weltbewegendes und sie ist absoluter Quatsch:
Wir haben eine Person, die ein Bierglas über einen Tisch wirft. Während das Bierglas über den Tisch fliegt, soll die Kamera mitscrollen (wie bei Angry Birds). Am Ende soll die Kamera stehen bleiben, dass Bier auf ein Trampolin fallen (oder auch nicht – je nachdem wie stark geworfen wurde) und dem Biertrinker, der faul auf der rechten Seite liegt, in den Mund gekippt werden.
Grundlagenforschung
Nachdem ich nun Google nach dem Thema „HTML 5 Canvas Games“ befragte, landete ich in dem Forum http://www.html5gamedevs.com in dem ich mich auch prompt registrierte um meine Idee den „Profis“ vorzustellen. Ich wollte mir Anregungen und Tipps holen, die mich bei der Umsetzung dieser Spieleidee als HTML5 Spiel befähigen.
Dazu schrieb ich diesen Forenbeitrag:
Während ich auf Antwort wartete, stöberte ich etwas in dem Forum und stieß auf die eigene Forenrubrik „Phaser.io“. Hierbei handelt es sich um ein HTML 5 Canvas Spieleframework, welches momentan scheinbar eine relativ weite Verbreitung hat.
Meine erster Beantworter auf den Forenbeitrag schlägt außerdem die Nutzung einer Bibliothek namens „PIXI.JS“ für das 2D Rendering vor, die angeblich auch in phaser.io vorhanden ist, ebenfalls wie diverse Spielephysik, auf die man direkt über die Phaser-Framework-Methoden zugreifen kann. Desweiteren gibt es Add-Ons, die man zwar für kleines Geld dazukaufen muss, aber welche die Funktionalitäten von Box2D hinzufügen:
http://phaser.io/shop
Hier ist eine Box2D Wasserpartikeldemo:
http://google.github.io/liquidfun/
Um kleine Javascripte auszuprobieren wurde auf der Seite von phaser.io folgendes Minitool empfohlen:
http://jsfiddle.net/
Entschluss
Ich werde mich daher in Phaser.io einarbeiten, da es als Werkzeugkasten die meisten Features für die Entwicklung von Spielen bietet.
Phaser kann man im Web unter der folgenden URL finden:
http://phaser.io/
Einstieg in Phaser.io / Erfahrungsbericht:
Die Entwicklungsumgebung
Zunächst stellt sich die Frage, welche Entwicklungsumgebung man nutzen möchte.
Da ich von Online-Quellcodeeditoren wie Codeanywhere begeistert bin, wollte ich die auf der Website phaser.io vorgeschlagene Cloud9-Variante testen. Hierbei handelt es sich ebenfalls um einen Online-Quellcodeeditor
http://c9.io <- Cloud9 Quellcodeditor
Erste Hürde: „First, sign up to the website using GitHub, and once this is completed, you will be redirected to your dashboard.“
Hierzu musste ich mich erstmal bei GitHub (ja hatte noch keinen Account 😉 ) anmelden und das Hello World Tutorial durchgehen, was mich 20 Minuten gekostet hat. Im Tutorial musste man einen „Branch“ anlegen und diesen mit dem „Master“ wieder vereinigen.
Der benannte Vorteil von GitHub: “ You don’t have to worry about losing data on your hard drive or managing a project across multiple computers“
Es lebe die Cloud!
In GitHub musste ich zunächst den Cloud9 Editor authorisieren auf mein Repository zugreifen zu dürfen:
„Authorize application
Cloud9 by @cloud9Deploy would like permission to access your account“
Auf dem Cloud9 Dashboard angelangt, erzeugt man ein neues Projekt von der URL
http://github.com/photonstorm/phaser.git
Diese URL scheint das komplette Phaser-Framework zu beinhalten.
Meine erste Überraschung beim Cloud9 Editor:
* Man kann PHP Code anlegen, der interpretiert wird
* Es gibt eine Ubuntu Command Line Zeile, in der man BASH-Kommandos ausführen kann
Der Cloud9 Editor bietet einen Debugger, den hatte ich für PHP schon länger gesucht, allerdings bleibt die Ausführung nicht bei den Breakpoints hängen. Evtl. muss man etwas konfigurieren?
Zurück zu phaser.io . Ich will ja erstmal mein Hello World Projekt erstellen :). Also mal gucken ob mir das die eingerichtete kostenlose Umgebung auch erlaubt…
Ich habe nun den gesammten root-Folder des Phaser-Ordners in den Ordner „Phaser“ kopiert, da man in der kostenlosen Version von Cloud9 nur einen Workspace nutzen darf.
Da ich mit Chrome arbeite, hat sich zum Switchen zwischen den Tabs (Editor <-> Tutorial <-> WordPress) die Tastenkombination STRG+BILD Hoch / STRG+Bild Runter als praktisch erwiesen. Auffällig ist, das der Cursorfokus des aktuellen Tabs nicht verloren geht.
Im Ordner phaser/Ressources/tutorials befinden sich alle Tutorials, die auf der Seite phaser.io aufgeführt sind. Ich hatte den Fehler gemacht über die Cloud9-Bashconsole die ZIP-Dateien mit wget runterzuladen und mit unzip zu entpacken. Dies ist unnötig.
Über den RUN-Button des Cloud9-Editors ist schnell eine geöffnete HTML-Datei geladen und mit dem Preview-Button auf den Bildschirm gebracht.
Schnell habe ich die ersten beiden Tutorials durch…
http://phaser.io/tutorials/making-your-first-phaser-game/part2
Es ist nicht nötig den Run-Button bei jedem Versuch neu zu klicken sondern es reicht aus den Refresh button zu klicken.
Fazit
* Die kostenlose Variante von Cloud9 (http://c9.io) ist sehr zu empfehlen.
* Ich hätte das GitHub Tutorial nicht benötigt, da lediglich GitHub für den Login von Cloud9 genutzt wird.
* Ich kann nun relativ schnell rechner- und ortsunabhängig an einem Canvas-Spiel entwickeln
Erste Schritte mit dem Framework
Meines Erachtens macht es durchaus Sinn auf der Hauptebene seines Cloud9 Workspace das Phaser-Framework mit den Tutorials als Nachschlagewerk zu nutzen. Die Hauptstruktur eines Phaser-Projektes sieht so aus:
var game = new Phaser.Game(800, 600, Phaser.AUTO, '', { preload: preload, create: create, update: update });
function preload() {
game.load.image('sky', 'assets/sky.png');
game.load.image('ground', 'assets/platform.png');
game.load.image('star', 'assets/star.png');
game.load.spritesheet('dude', 'assets/dude.png', 32, 48);
}
var platforms, player, cursors, stars;
var score = 0;
var scoreText;
function create() {
// We're going to be using physics, so enable the Arcade Physics system
game.physics.startSystem(Phaser.Physics.ARCADE);
// A simple background for our game
game.add.sprite(0, 0, 'sky');
// The platforms group contains the ground and the 2 ledges we can jump on
platforms = game.add.group();
// We will enable physics for any object that is created in this group
platforms.enableBody = true;
// Here we create the ground.
var ground = platforms.create(0, game.world.height - 64, 'ground');
// Scale it to fit the width of the game (the original sprite is 400x32 in size)
ground.scale.setTo(2, 2);
// This stops it from falling away when you jump on it
ground.body.immovable = true;
// Now let's create two ledges
var ledge = platforms.create(400, 400, 'ground');
ledge.body.immovable = true;
ledge = platforms.create(-150, 250, 'ground');
ledge.body.immovable = true;
// The player and its settings
player = game.add.sprite(32, game.world.height - 150, 'dude');
// We need to enable physics on the player
game.physics.arcade.enable(player);
// Player physics properties. Give the little guy a slight bounce.
player.body.bounce.y = 0.2;
player.body.gravity.y = 300;
player.body.collideWorldBounds = true;
// Our two animations, walking left and right.
player.animations.add('left', [0, 1, 2, 3], 10, true);
player.animations.add('right', [5, 6, 7, 8], 10, true);
cursors = game.input.keyboard.createCursorKeys();
stars = game.add.group();
stars.enableBody = true;
// Here we'll create 12 of them evenly spaced apart
for (var i = 0; i < 12; i++)
{
// Create a star inside of the 'stars' group
var star = stars.create(i * 70, 0, 'star');
// Let gravity do its thing
star.body.gravity.y = 6;
// This just gives each star a slightly random bounce value
star.body.bounce.y = 0.7 + Math.random() * 0.2;
}
scoreText = game.add.text(16, 16, 'score: 0', { fontSize: '32px', fill: '#000' });
}
function update() {
// Collide the player and the stars with the platforms
game.physics.arcade.collide(player, platforms);
// Reset the players velocity (movement)
player.body.velocity.x = 0;
if (cursors.left.isDown)
{
// Move to the left
player.body.velocity.x = -150;
player.animations.play('left');
}
else if (cursors.right.isDown)
{
// Move to the right
player.body.velocity.x = 150;
player.animations.play('right');
}
else
{
// Stand still
player.animations.stop();
player.frame = 4;
}
// Allow the player to jump if they are touching the ground.
if (cursors.up.isDown && player.body.touching.down)
{
player.body.velocity.y = -350;
}
// Prüfe ob die Sterne auf die Plattform treffen
game.physics.arcade.collide(stars, platforms);
// Prüfe ob der Spieler mit einem Stern kollidiert, falls ja gehe in die
// Funktion collectStar
game.physics.arcade.overlap(player, stars, collectStar, null, this);
}
function collectStar (player, star) {
// Removes the star from the screen
star.kill();
// Add and update the score
score += 10;
scoreText.text = 'Score: ' + score;
}
Fazit
* In der Preload-Methode werden die Grafiken (PNGs) geladen. Spritesheets sind dabei Animationen, die als PNG vorliegen und die einzelnen Frames nebeneinander beinhalten.
* Die Objekte werden mit game.add.sprite in der entsprechenden Reihenfolge in der Create-Methode hinzugefügt
* Phaser besitzt 3 Physikengines. wobei Arcade die einfachste sein soll
** Arcade Physics
** Ninja Physics
** P2.JS Full-Body Physics
* Kollisionen werden immer in der Update-Prozedur abgefragt
* Tastatureingaben werden in der Update-Prozedur abgefragt
* Velocity ist die Geschwindigkeit, die ein Objekt bekommt
Anwendbarkeit
Wir haben hier eine fixe Welt, ich möchte aber sowas wie ein scorllendes Spiel nach dem Angry Birds Vorbild haben. Dafür brauche ich ein Beispiel. Die Frage ist, ob man Tilemaps, welche vorwiegend für scrollende Jump-and-runs wie Super Mario oder Giana Sisters verwendet werden benutzen sollte.
Ich suche also ein Beispiel das ich idealerweise nutzen kann…
Durchgehen der Phaser.io Examples
N
Debugging
Der Cloud9 Editor bietet die Möglichkeit, Break Points zu setzen. Ob diese Breakpoints nun das PHP oder Javascript debuggen können habe ich nicht rausgefunden, da sie keine Auswirkung haben. Allerdings hat mein Google Chrome Debugger auch recht nützliche Funktionen für das Debuggen. Nachteil ist, das man die Cloud9 Umgebung kurz verlassen muss. Man kann allerdings die URL (siehe Screenshot) des gestarteteten Webservers einfach in einen neuen Tab pasten.
Hierbei wunder ich mich wie lange dieser Webserver von c9.io laufen wird, da er ja für einen kostenlosen Account massig Systemressourcen frisst.