pygbag: Vom Python-Skript zum Browserspiel

Das PyGame-Tutorial-Spielchen „Snowangel“ läuft mit pygbag als Browser-Game in Chrome.
Das PyGame-Tutorial-Spielchen „Snowangel“ läuft mit pygbag als Browser-Game in Chrome.

Es hat sich herumgesprochen, dass man mit Python und PyGame schöne kleine Computer-Games programmieren kann. Sie müssen jedoch keine Skripte bleiben, weil es nicht viel braucht, sie in ein Browsergame umzuwandeln.

Die Programmiersprache Python und die Python-Spiele-Bibliothek PyGame haben sich über die Jahre eine Fan-Gemeinde erobert – und besonders im schulischen Einsatz sind sie sehr praktisch, weil Python keine so hohen Hürden setzt wie Java, Rust oder gar C++. Um ein Computerspiel in Python mit PyGame zu erstellen, braucht es nur wenige Zeilen und es gibt im Netz zuhauf Anleitungen, wie man damit sogar in relativ kurzer Zeit anspruchsvolle Anwendungen erstellen kann. Viele Projekte auf itch.io sind Python-basiert.

Nachteil von Python-Games ist, dass sie weiterhin erst mal bloß Skripte sind, deren Quelltexte erst einmal offen bleiben (womit ein Freeware-Programmierer aber leben kann). Python-Skripte setzen zur Ausführung allerdings auch einen Python-Interpreter mit installierten Hilfsbibliotheken voraus. Das macht die Verteilung von Anwendungen etwas schwieriger. Wenn man nur kleine Games an seine Freunde verteilen will, ist die Installation einer kompletten Laufzeitumgebung zu aufwendig. Zumal viele Computeranwender inzwischen – aus guten Gründen – nicht mehr einfach so irgendwelche Software auf ihrem PC installieren.

Das ist einer der Gründe, warum Browser-Games so beliebt sind: Sie laufen im Webbrowser, ohne eine Installation zu benötigen. Und auch mit Python und PyGame kann man recht einfach solche Spiele erstellen, es braucht nur die Bibliothek PygBag und ein paar Zeilen Änderungen im Quelltext.

Browser-Games mit PygBag

Um ein Browser-Game aus einem Python-Skript zu machen, benötigt man zunächst einmal ein (vorhandenes) Python-Skript mit PyGame. Es sollte möglichst keine betriebssystemspezifischen Code-Zeilen enthalten, weil diese in der Webumgebung womöglich nicht funktionieren. Gerade auch bei GUI-Bibliotheken muss man darauf achten, dass diese gerne einmal den Fokus an sich reißen. Deshalb sollte man für ein Browserspiel möglichst auch kein TKinter verwenden. Es gibt aber eine ganze Reihe von PyGame-kompatiblen GUI-Bibliotheken, die sich verwenden lassen, beispielsweise pygame-gui.

1. pygbag installieren

Dann benötigt man noch die Bibliothek pygbag, die man per pip-Befehl installieren kann:

pip install pygbag

2. Projekt neu ordnen

Wenn pygbag erfolgreich installiert wurde, muss man als nächstes einige Änderungen am Projekt vornehmen:

Als Erstes muss die Hauptdatei des PyGame-Projekts in main.py umbenannt werden, denn pygbag sucht später diese Datei, wenn sie das Paket für den Webbrowser schnürt.

Was die Verzeichnisstruktur des PyGame-Projekts angeht, setzt pygbag voraus, dass sich die Skriptdateien im Stammverzeichnis finden, die Assets (also Grafiken und Sounds) in Verzeichnissen darunter. An diese Ordnung muss man sich halten, sonst werden die Dateien womöglich nicht richtig geladen.

3. Programm anpassen

Hauptdatei modifizieren

Dann muss in die Unit  main.py die Library asyncio über einen Import-Befehl eingebunden werden:

import asyncio

Die Hauptschleife des PyGame-Programmes muss in eine Funktion gepackt werden, die def main() heißt, dieser muss das Attribut „async“ vorangestellt werden. In dieser Main-Funktion muss auch zwingend ein Passus „await asyncio.sleep(0)“ eingefügt werden:


async def main():
    while True:
        # Hier kommt der Code der PyGame-Hauptschleife rein
        pygame.display.update()
        await asyncio.sleep(0) # Dieser Befehl ist zwingend.
        clock.tick(60)

Ganz unten in das Hauptskript main.py muss als letzte Zeile noch der Funktionsaufruf von asyncio.run() folgen. Dies sollte die letzte Zeile im Skript sein:


asyncio.run(main())

Hat man diese Änderungen vorgenommen, sollte man das Skript testweise nochmal so laufen lassen und schauen, ob alles weiterhin ordnungsgemäß funktioniert. (Was der Fall sein sollte.)

4. Skript und Dateien mit pygbag packen

Als nächstes kann man im Terminal pygbag aufrufen und ihm befehlen, das Skript und sämtliche verwendete Dateien in ein Webpacket umzuwandeln. Dazu kann man entweder pygbag im Verzeichnis ausführen mit Angabe der Hauptdatei:

pygbag main.py

Oder aber, man gibt den ganzen Projekteordner an, indem man pygbag eine Ebene höher aufruft und ihm dann den Verzeichnisnamen mitgibt.

Wichtig: In jedem Fall wird pygbag alle(!) Dateien, die es im Projektverzeichnis vorfindet, zu einem Webpaket schnüren. In diesem Verzeichnis sollten sich also nur solche Dateien befinden, die für die Ausführung des Skripts notwendig sind!

pygbag startet nach seinem Aufruf dann auch einen lokalen Webserver, mit dem man das Ergebnis testen kann – was man auch tun sollte. Man kann darauf zugreifen, wenn man einen Webbrowser öffnet und dort folgende URL eingibt:

http://localhost:8000/

Wenn alles geklappt hat, öffnet der Webbrowser dann ein Webassembly, welches das Spiel im Browser ausführt:

 

Wenn pygbag das Python-Spiel erfolgreich übersetzt hat, kann man es testen.
Wenn pygbag das Python-Spiel erfolgreich übersetzt hat, kann man es testen.

Klickt man auf den Schriftzug „Ready to start!“, wird das Browserspiel gestartet.

Zusätzliche Anpassungen für Zusatzbibliotheken

Wenn man Zusatzbibliotheken wie die GUI-Bibliothek pygame_gui in seinem Programm verwendet, muss man das Webassembly noch anweisen, per „Requirements“-Anweisung diese weiteren Bibliotheken nachzuladen. Das geht, indem man folgenden Text ganz oben(!) in die main.py einfügt. (Diese zusätzlichen Anweisungen sehen zwar wie ein Kommentar aus, müssen aber wirklich ganz oben in den Kopf der Hauptdatei main.py:

# /// script
# dependencies = [
# "pygame-ce",
# "pygame-gui",
# "python-i18n",
# ]
# ///

5. Export der Webdateien

Wenn pygbag erfolgreich ausgeführt wurde, findet man im Projektverzeichnis einen neuen Unterordner vor mit dem Namen „build“ – dort finden sich zwei Ordner: „web“ und „web-cache“. Wichtig für den Export ist die Datei „web“, darin sollten sich drei Dateien befinden:

favicon.png – das ist ein Symbolbild für den Webbrowser

index.html – das ist die HTML-Containerdatei für das Webassembly, sie lädt per CDN die von PygBag benötigten Dateien und die vom Programm verwendeten Skripte und Assets.

programmname.apk – in diese Datei wurden von pygbag der Quelltext und die vom Programm verwendeten Skripte und Assets gepackt.

Diese drei Dateien müssen dann auf einen Webserver hochgeladen werden, beispielsweise beim Dienst itch.io, der von den pygbag-Entwicklern empfohlen wird, oder in ein Verzeichnis auf einem eigenen Webserver.

Somit sollten die meisten PyGame-Skripte in ein Browser-Game umzuwandeln sein. Das PyGame-Tutorial-Spielchen „Snowangel“ (basierend auf der Version von Max Kubierschky aus dem Jahr 2009), sieht in der leicht erweiterten Fassung aus dem Python-Unterricht der Informatik-AG beispielsweise so aus:

Das PyGame-Tutorial-Spielchen „Snowangel“ läuft mit pygbag als Browser-Game in Chrome.
Das PyGame-Tutorial-Spielchen „Snowangel“ läuft mit pygbag als Browser-Game in Chrome.

Das kleine Beispiel-Spielchen kann man hier selbst ausprobieren:

Fehlerbehebung

Glücklich ist, wessen Programm auf Anhieb funktioniert. Da dies in der Welt der Programmierung aber nicht der Standard-Fall ist, bietet pygbag noch eine Debugumgebung. Diese ruft man auf, indem man „#debug“ an die Browserzeile anhängt. Das geht sowohl im lokalen Webserver als auch später, wenn die Dateien auf dem eigenen Webserver liegen:

http://localhost:8000/#debug

Dann startet die pygbag-Umgebung im Browser mit Debug-Konsole:

Test im lokalen Webserver mit Debug-Konsole
Test im lokalen Webserver mit Debug-Konsole

Allerdings kann der Debug-Modus nur ausgeführt werden, wenn das Webassembly selbst erfolgreich starten konnte. Versagt schon die Laderoutine (was ein beliebter Serverfehler ist), wird das nicht angezeigt.

Fehlerbehebung auf dem Webserver

Es kommt bisweilen vor, dass die von pygbag erstellen Dateien nicht auf dem eigenen Webserver ausgeführt werden. Dann startet das Browserspiel entweder gar nicht, oder man erhält kryptische Fehlermeldungen.

Hier ein paar typische Fehler:

1. Nichts passiert

Wenn gar nichts passiert, kann das unterschiedliche Gründe haben:

  1. Es liegt am Browser: Manche Browser unterstützen keine WebAssembly oder nur begrenzt, dann sollte man verschiedene Webbrowser testen. Chrome und Firefox funktionieren fast immer, ebenso wie Edge, Safari unter MacOS oder gar iOS ist etwas eigen, überhaupt sind Tablet-Browser oft nicht geeignet.
  2. Es liegt am Gerät: Manche sehr alten Geräte oder Mobilgeräte verfügen nicht über genug Rechenkraft oder Arbeitsspeicher, um ein WebAssembly auszuführen.
  3. Es liegt am Provider: pygbag lädt die Laufzeitdateien für Python und PyGame von einem anderen Server nach. Das unterstützen nicht alle Provider (Content-Policy). Je nach Provider-Einstellungen laufen WebAssemblys auch nicht in verschachtelten Unterverzeichnissen auf dem Server – dann muss der Ordner mit den pygbag-Dateien zwingend in das Wurzelverzeichnis auf dem Webspace.

2. Fehler „i.fs is undefined“

Ein besonders ärgerlicher Fehler ist, wenn der Browser den Fehler „i.fs is undefined“ anzeigt – der Fehler ist zwar oft sehr leicht zu beheben, aber man muss erst mal darauf kommen, was schiefgegangen ist, weil hier auch die Debug-Konsole nicht weiterhilft.

Erscheint die Fehlermeldung "i.fs is undefined" oder wird nur ein leerer grüner Balken angezeigt, hat es meist nicht geklappt, die .APK-Datei zu laden.
Erscheint die Fehlermeldung „i.fs is undefined“ oder wird nur ein leerer grüner Balken angezeigt, hat es meist nicht geklappt, die .APK-Datei zu laden.

Der Fehler „i.fs is undefined“ wird angezeigt, wenn das Paket mit den Assets nicht richtig nachgeladen werden konnte. Das kann entweder daran liegen, dass die .APK-Datei nicht gefunden wurde (weil sie im falschen Verzeichnis liegt), oder aber es liegt daran, dass der Server den passenden MIME-Type nur über die Dateiendung erkennt, dieser ist ZIP.

Tatsächlich ist .APK-Datei, wohinein pygbag die Quelltexte und Assets gesteckt hat, nämlich in Wirklichkeit nichts anderes als ein ZIP-Archiv. Deshalb hilft es manchmal, den Dateiendung entsprechend einfach in „*.zip“ umzubenennen – natürlich muss man dann noch die Zeile 87 in der Datei „index.html“ ändern, wo die APK-Datei angeführt ist – dort sollte dann der neue Dateiname mit der ZIP-Endung stehen:

Also statt:

apk = "programmname.apk"
dann:
apk = "programmname.zip"

Bei Providern wie Strato hilft das schon, damit das Browserspiel dann wie gewünscht startet.

3. Inkompatibilitäten mit Python-Libraries

pygbag unterstützt nicht alle Python-Libraries – daher sollte man nur sehr sparsam einsetzen. Wichtig ist auch der Hinweis, dass pygbag den Pygame-Fork pygame-ce verwendet. Dieser unterscheidet sich nicht stark vom Hauptprojekte, im August 2024 liegt pygame-ce aber erst in Version 2.5.1 vor, während pygame bereits Version 2.6 aufweist. In sehr seltenen Fällen könnte es hier daher Unterschiede geben.

Python-GUI-Bibliotheken funktionieren nicht so ohne weiteres mit pygbag. Eine der Ausnahmen ist pygame-gui – aber auch diese Bibliothek muss man, wie oben schon angeführt, in der Requirement-Anweisung ganz oben in der main.py explizit aufführen:

 
# /// script 
# dependencies = [ 
# "pygame-ce", 
# "pygame-gui", 
# "python-i18n", 
# ] 
# /// 

Vergisst man die Abhängigkeiten anzugeben, bleibt der Bildschirm meist schwarz.

4. Speicherfehler und Performanz

Was für Browserspiele generell gilt, nämlich möglichst Speicherplatz zu sparen wo es geht, gilt natürlich auch für Browserspiele mit pygbag: Die Entwickler legen nahe, auf zu große Dateien zu verzichten. Insbesondere Sound-Dateien sollten im OGG-Format vorliegen und niemals als WAV-File. Auch Grafiken sind möglichst klein zu halten.

Hilfe aus der Community

Pygame und auch pygbag haben eine aktive Community, die in der Regel sehr hilfsbereit ist.

Man kann mit ihr beispielsweise über ihren Discord-Server in Kontakt treten:

Über Martin Dühning 1520 Artikel
Martin Dühning, geb. 1975, studierte Germanistik, kath. Theologie und Geschichte in Freiburg im Breisgau sowie Informatik in Konstanz, arbeitet als Lehrkraft am Hochrhein-Gymnasium in Waldshut und ist Gründer, Herausgeber und Chefredakteur von Anastratin.de.