Von 100KB auf 8854 Byte mit einem HTML5 Spiel

Die Motivation für dieses Projekt entstand nach der Demo Party Revision 2022. Das Ziel war es, ein weiteres Spiel zu schreiben, das für die Demoscene relevant wäre. Statt nur einer Referenz wurden es dann zwei. Nicht nur, dass die Spielmechanik einem Amiga-Freeware-Spiel aus dem AmiNet entsprang, das ich irgendwann in den späten 90er Jahren gefunden hatte. Auch das Minimieren des JavaScript-Codes auf einen Bruchteil seiner Größe war passend. Und so begann eine spannende Reise in eine unbekannte Welt.

Ich startete mit einer Version, die noch nicht auf Größe optimiert war, abgesehen davon, dass keine Frameworks für das Spiel verwendet wurden. Der Audioplayer war bereits auf geringen Platzverbrauch optimiert und ich füllte ihn nur mit den Songs. An dieser Stelle möchte ich meinem alten Freund einen riesigen Dank aussprechen, der so freundlich war und auch nerdig genug, um mit ihm unbekannter Software zwei Stücke für mich zu erstellen. Der Song beim Laden und Generieren stammt von mir, da ich auch etwas dazu beitragen wollte und ausprobieren wollte, ob es so früh schon möglich ist.

Der nächste Schritt war die Erstellung der Grafiken, die ich während eines Filmabends erstellte. Ursprünglich waren sie nur als Platzhalter gedacht, blieben aber fast unverändert im Spiel. Und dann das Programmieren des eigentlichen Spiels. Dies stellte kaum eine Herausforderung dar, da alle benötigten Komponenten aus Erfahrungen stammten. Einen Teil der Struktur entlehnte ich dem Phaser.js-Framework, mit dem ich viel gearbeitet hatte. Etwas Neues bot dann erst wieder der spätere Optimierungsabschnitt 🙂

Diese Version kommt jetzt auf knapp über 100 KB JavaScript und Bilder, die jeweils als separate Dateien geladen werden. Zuerst ersetzte ich die Grafiken für die Wolken, die Berge und den Himmel durch eine Funktion. Diese erzeugt auf einem nicht sichtbaren Canvas dann die Bildinformationen, die zuvor geladen werden mussten.

Die Einsparungen in Bytes an dieser Stelle waren höchst unterschiedlich. Der Himmel war erst nach der Minimierung des JavaScript-Codes deutlich kleiner als das PNG. Die Wolken sahen am Ende nicht nur besser aus und konnten mehr, sondern die Reduzierung von 3105 Byte auf 910 Byte kann sich auch sehen lassen. Den Rest der Grafikelemente wollte ich nicht generieren lassen. In bewährter Manier wanderten sie in eine Spritemap, die aus einem einzigen Bild besteht, aus dem dann jeweils Kacheln ausgestanzt werden. So bleiben am Ende aller Verbesserungen für den Programmcode noch 43204 Byte und das eine Bild mit 3885 Byte.

Das ist eine Ersparnis von über 50% und kann sich schon sehen lassen. Aber das war nur der einfache Teil der Aufgabe, denn wir wissen, da geht noch mehr. Ab hier sollten einfach die unterschiedlichen Tools der Reihe nach ausprobiert werden und verglichen werden, wo die besten Ergebnisse erzielt werden können. Vor dem letzten Schritt muss jedoch noch einmal mehr Platz aufgewendet werden. Statt das Bild zu laden, wandert es als Base64-Textinformation in den Code und der Platzbedarf steigt auf über 52 KB. Tage der weiteren Reduktion von Redundanzen drückten die Summe auf 44017 Byte. Der Google Closure Compiler machte daraus dann schlanke 33538 Byte. Man merkt schon, dass bei diesen Abschnitten nicht mehr viel herausspringt. But wait, there is more.

Die wirkliche Magie ist bereit für ihre Arbeit, aber zuvor noch einmal kurz weiter ausgeholt. In der Demoscene ist das Optimieren auf Größe eine der ältesten Disziplinen überhaupt. Bei mir erzeugte seinerzeit Farbrausch – fr-08: .the .product mit einer Dateigröße von 64 KB eine 10 Minuten lange selbst ablaufende Fahrt durch eine 3D-Welt und erzeugte dabei Gigabyte-weise Texturen und einen Soundtrack in CD-Qualität. Ja, liebe Kinder, Anfang der 2000er Jahre war CD-Qualität der höchste zu erreichende Standard überhaupt 🙂 Das war natürlich nur mit viel Rechenkapazität und einem Umfeld möglich, das schon einiges mitbringt. In diesem Fall ein Windows-PC mit installiertem DirectX, das beim Darstellen von 3D-Welten sehr hilfreich ist.

Was vor 20 Jahren nur ein Betriebssystem konnte, kann heute schon ein Webbrowser bieten. In diesem finden sich viele nützliche Dinge, die uns eine multimediale Zukunft ermöglichen. Schlaue Köpfe aus der Szene haben einige Wege gefunden, den Platzbedarf zu optimieren und das Bündeln in eine einzige Datei zu bewerkstelligen. Der verwendete Synthesizer stammt auch genau aus einem solchen Bestreben und ist sehr populär. Für unseren Fall verwenden wir das Portable Network Graphics-Format, das uns die Komprimierung und Dekomprimierung abnimmt. Unser Sourcecode wandeln wir in Pixel um, die im Bild gespeichert werden. Dank einer besonderen Behandlung im Browser kann hier auch eine kleine Routine mitverpackt werden, die das JavaScript wiederherstellt.

Und schon ist es geschafft, unser Quelltext muss sich jetzt nur noch selbst starten und mit dem Ausgangspunkt im Browser klarkommen. Da jede benötigte Information in Textform vorliegt, kann das Spiel wie gewohnt weitergehen. Die Datei hat jetzt nur noch eine Gesamtgröße von 8854 Byte.

Es war eine sehr interessante Reise mit vielen erhellenden Momenten, die mir wieder einmal gezeigt haben, dass man immer noch etwas dazulernen kann. Vor allem, wenn ein paar Leitplanken eingezogen werden, die eine unbekannte Richtung vorgeben. Eingereiht in das Portfolio an fertigen Spielen macht es sich für seine Art der Lösung sehr gut und eröffnet Raum für den nächsten Schritt auf den Stufen nach oben.
Lesebare Version des Spieles TheSun
PNG HTML Version des Spieles TheSun