Schlagwort-Archive: Spacola

Eines meiner heiligsten Prinzipien bei der Entwicklung meines Remakes von Spacola ist Authentizität. In dieser Hinsicht bin ich leider ein Perfektionist. Zumindest so weit es mir technisch möglich ist, versuche ich mich immer zu 100% an den Originaldateien und an Originalmechanismen zu orientieren, und ich weiche nur davon ab, wenn es absolut nötig, wirklich sinnvoll, oder mit meinem Know-How sonst nicht machbar ist. Zu Beginn der Entwicklung konnte ich lediglich rein aus der Beobachtung nachimplementieren, ich musste notgedrungen tausende selbsterstellte Screenshots verarbeiten und Tonaufnahmen aus dem Emulator aufnehmen. Das Ergebnis war natürlich oft nah am Original dran, aber für mich nie authentisch genug. Glücklicherweise habe ich mittlerweile so einige Fortschritte gemacht, die mir meine Mission deutlich erleichtern. In den vergangenen Wochen habe ich einen äußerst wichtigen Meilenstein bei der Analyse des Originalspiels erreicht. Um verstehen zu können, was mir da konkret gelungen ist, muss ich etwas weiter ausholen. Daher hier ein kleiner technischer Exkurs in meine Welt.

Schon wie zuvor im 1990 veröffentlichten OXYD hat Spacola einen eigenen Kopierschutz in Form eines Dongles (das Codebuch). Im Gegensatz dazu sind die Codes allerdings mittlerweile ein integraler Bestandteil des Gameplays geworden, und nicht mehr nur Steine, die den Weg blockieren. Den Kopierschutz schlicht auszubauen hätte im einfachsten Fall bedeutet, direkt das Gameplay von Spacola zu verändern, die Siegbedingungen im Spiel zu entfernen; das Spiel wäre quasi sinnlos geworden. (Spoiler-Warnung: Dennoch ist einem findigen Entwickler vor wenigen Jahren auch das schon auf intelligente Weise gelungen.) Weiterhin bringt das Spiel jedoch noch einen raffinierten Crackschutz mit, um zu verhindern, dass der Kopierschutz überhaupt angegriffen werden kann. Die Daten der Dongleware-Spiele bis einschließlich OXYD lagen noch offen da, wenn auch in proprietären Dateiformaten (SHL, IMG, CMP, PAC), mit denen man so jedenfalls nichts anfangen konnte, bis auf die Sounddateien, die einfach im Rohformat vorhanden waren. Da OXYD schließlich geknackt werden konnte (und auch das Codebuch trotz absichtlich schlechtem Farbkontrast kopiert wurde), wurden die Daten in Spacola inzwischen gegen unbefugte Zugriffe geschützt. Dies macht es natürlich für interessierte Remake-Entwickler wie mich deutlich schwieriger, die eigentlich nicht den Kopierschutz entfernen wollen, sondern Einblick in die Spieldaten brauchen.

Wie sieht dieser Crackschutz nun eigentlich aus? Bei Spacola lagen weder die Spieldaten noch die ausführbare Datei in lesbarer Form auf der Diskette vor. Auf dieser gab es lediglich ein großes mit PFXPak erstelltes, selbstextrahierendes Programm, das das Spiel zur Laufzeit ausschließlich in den Arbeitsspeicher entpackt und dort ausführt. Laut PFXPak-Dokumentation bringt das nicht nur den Vorteil, dass man mehr nutzbaren Netto-Speicherplatz auf der Diskette hat, sondern auch Performance-Verbesserungen, da weniger Daten über das langsame Diskettenlaufwerk geladen werden müssen. Außerdem werden zum einen die einzelnen Dateien immer erst dann entpackt, sobald sie vom Programm referenziert, also im Spiel benötigt werden, zum anderen werden die Dateien auch gleich noch dekodiert, da sie teilweise nur in verschlüsselter Form vorliegen. Und selbst das ist noch nicht alles: Sogar wer glaubt, es sei ihm gelungen, das integrierte LHarc-Archiv des Entpackers aus der Datei zu extrahieren, und dieses von Hand entpacken will, erhält leider kein Spacola, sondern nur ein Programm, das eine kleine Grußbotschaft an den Hacker auf dem Bildschirm anzeigt und gleichzeitig die Festplatte vollmüllt, sofern eine angeschlossen ist. Ja, man musste sich als Spieleentwickler wohl irgendwie gegen Raubkopierer zur Wehr setzen. Der wenig freundliche Inhalt besagter Grußbotschaft wurde mit dem ersten und wahrscheinlich einzigen Spacola-Patch einige Wochen später zensiert.

Wer sich mit Atari ST-Emulation intensiver befasst, weiß, dass es mit dem STeem Debugger ein äußerst mächtiges Debugging-Werkzeug gibt, das genutzt werden kann, um sämtliche ST-Software zu analysieren und zu modifizieren. Fürs Reverse-Engineering ist ein brauchbarer Debugger quasi unverzichtbar. Als ich vor etlichen Jahren zum ersten Mal die Oberfläche des Debuggers öffnete, war ich wie erschlagen von den endlosen Möglichkeiten, die sich mir hier boten. Und mir war sofort klar, dass ich nicht die nötigen Fähigkeiten hatte, um hier irgendetwas zu bewegen, denn natürlich setzt so ein Debugger unter anderem auch ein tieferes Verständnis der Hardware voraus. In meinem Studium hatte ich wenigstens zwei Semester Rechnertechnik, in welchen ich die Grundlagen von 68K-Assembly lernte und auch sehr kleine Programme schrieb. Dies brachte mich zumindest theoretisch in die Lage, die Funktionen des Debuggers rudimentär zu verstehen. Doch als ich mich damals spaßeshalber in ein laufendes Programm einklinkte, Schritt für Schritt durch den Programmcode bewegte, und die Hieroglyphen verstehen wollte, die der Prozessor da ausführte, hörte der Spaß irgendwie auf. Mein Verstand konnte zwar mühsam und sehr langsam erfassen, was dort in jeder Zeile ausgeführt wurde, aber mir fehlte jeglicher Durchblick dafür, warum es ausgeführt wurde, an welcher Aufgabe der Programmcode gerade arbeitete. Es gab keinen Kontext. Es ist ein bisschen so als würde ich mir unter einem Mikroskop nacheinander die einzelnen Holzfasern genauer anschauen, um dadurch herausfinden zu wollen, worum es in dem Buch geht. Dabei könnte ich nicht einmal erkennen, welchen Buchstaben ich mir da gerade ansehe.

Der STeem Debugger mit laufendem Spacola beim Ladevorgang

Aber die ersten kleinen Fortschritte ermutigten mich, den Kopf nicht hängen zu lassen. Der Memory-Browser des Debuggers bietet zum Beispiel eine Suchfunktion und erlaubt das Editieren des Speichers zur Laufzeit. So kann man Texte in den Programmen finden und ersetzen, was nette Spielereien ermöglicht. Eine andere nützliche Funktion ist der Speicherdump, der es erlaubt, den kompletten Arbeitsspeicher in eine Datei zu schreiben. Mit diesem wertvollen Hilfsmittel hatte ich endlich einen ersten direkten Zugang zu vielen Spielinhalten, wenn es auch noch lange nicht lückenlos war. Im Audiobearbeitungsprogramm Audacity konnte ich dieses Speicherabbild als Rohdaten einlesen und die Sounds von Spacola hörbar machen und grob „ausschneiden“, was mir wirklich enorm half. Eines meiner Probleme mit dieser Methode war jedoch, dass ich nie wusste, wo eine Datei beginnt oder aufhört. Die Dateien waren nicht byteperfekt. Und jahrelang waren die Audiodateien leider die einzigen, auf die ich dadurch Zugriff erlangen konnte. Ich wollte aber unbedingt auch an die Grafikdateien herankommen. Später gelang es mir mit großem Aufwand, das „Rentenbescheid“-Bild, das nach gewonnenem Spiel als Urkunde zum Ausdrucken verwendet wird, zu extrahieren. Die Monochrom-Rohdaten habe ich unter anderem durch einen emulierten Drucker als virtuelle Hardcopy in eine Datei schreiben lassen, mühsam rekonstruiert und mit STAD v1.3 laden können. Dadurch konnte ich einen Screenshot anfertigen. Dies war ein weiterer Motivationsschub, der mich daran glauben ließ, irgendwann alles zu schaffen.

Ende 2018 begann ich erneut damit, das Originalspiel aufwändig Schritt für Schritt im Debugger zu beobachten. Ich hatte erst angefangen, mich mit den Breakpoints und den Read- und Write-Monitors vertraut zu machen, und war überzeugt davon, ich könnte die entpackten Dateien abfangen, während sie gerade in den Arbeitsspeicher geschrieben werden. Im selbstextrahierenden Programm gibt es glücklicherweise eine Dateitabelle, die Dateinamen, Dateigrößen und Byte-Offsets enthält. Dies war letztlich der Schlüssel zum Erfolg. Jemand mit mehr Erfahrung im Reverse-Engineering hätte natürlich sofort gewusst, was hier zu tun ist. Ich musste es erst durch unzählige Fehlversuche und Rückschläge lernen. Am Ende dauerte es bis zum Frühjahr 2020, dann hatte ich endlich einen Plan. Durch das geschickte Setzen der Read- und Write-Monitors und Zurückverfolgen der Lese- und Schreibzugriffe, konnte ich genau den Teil des Codes ausmachen, der direkt für das Entpacken aller Dateien zuständig ist. Anschließend musste ich nur noch den Program Counter, die Schleifendurchläufe und die Adress- und Datenregister überwachen, dadurch konnte ich sehen, welche Datei gerade verarbeitet wurde, wo die Daten gelesen und wohin sie geschrieben wurden, und wann der Schreibvorgang exakt beendet ist. Ich führte Notizen darüber, welche Dateien ich dadurch erhalten konnte und ob sie die richtige Größe haben, um ihre Richtigkeit zu verifizieren.

Das Debugging beim Entpacken der Dateien

Das Modifizieren der Dateitabelle im Programm erlaubte es mir sogar, den Entpacker dazu zu bringen, die „falschen“ Dateien zu entpacken, darunter auch eine Sounddatei, die offenbar gar nicht referenziert, also im Spiel selbst niemals verwendet wird. Dies war immens hilfreich und verkürzte die weitere Zeit, um auch die letzten verbliebenen Dateien zu bekommen. Später bemerkte ich noch, dass Spacola leider wieder mal schlauer war als ich: Viele Sounddateien wurden im Spiel komprimiert, d.h. in der Größe reduziert, andere Sounddateien wurden aber nur in irgendeiner Weise kodiert, also bei gleicher Dateigröße unlesbar gemacht. Hierzu musste ich einen weiteren Codeabschnitt ausfindig machen, der Sounddateien entschlüsselt. Die zentralen Breakpoints waren mir in der Folge heilig, ich habe sie akribisch notiert und verwendet, um nacheinander alle 104 Dateien mühsam zu entpacken, aus dem Memory-Browser zu extrahieren und mittels HEX-Editor byte-perfekt auf die Festplatte zu schreiben. Das Ergebnis sind 557 KByte an Rohdateien, die exakt so im Originalspiel verwendet werden: 50 Sounddateien, 48 Sprite-Dateien, vier Bilddateien, eine Textdatei und eine IMG-Datei. Als Bonus erhielt ich auch die ungeschützte SPACOLA.PRG, also die ausführbare Datei ohne den Packer. Diese lässt sich auch starten und lädt sogar das Titelbild, anschließend hängt sie sich leider auf. Allerdings habe ich mich entschlossen, dieses Problem nicht weiter zu verfolgen, da es sich wahrscheinlich nicht lohnt.

Für mich war das bis hierhin schon ein großartiger Durchbruch. Dies war ein Thema, das mir noch Jahre zuvor wie eine unlösbare Aufgabe erschien, und plötzlich liegen mir alle Daten offen, um sie endlich in unberührter Form in meinem Remake zu verwenden. Aber da war natürlich weiterhin diese eine nicht ganz unbedeutende Hürde: Das selbstentwickelte Dateiformat der Sprite-Dateien ist leider unbekannt, undokumentiert und es gibt kein öffentlich verfügbares Programm, das die Dateien lesen könnte. Scheint so, als sei ich in einer Sackgasse gelandet.

Und in der nächsten Folge lesen Sie: Die Sprites von Spacola.

Wieder ist beinahe ein Jahr vergangen, seit ich den letzten Statusbericht zum SPACOLA-Remake abgeliefert habe, daher ist es nun ganz dringend an der Zeit, ein bisschen über die aktuellen Neuerungen seitdem zu plaudern. Bekanntlich habe ich eine ausgedehnte Winterpause eingelegt, so dass die Änderungen sich insgesamt in Grenzen halten, aber ein paar Fortschritte gab es durchaus. Die Entwicklung an dem Spiel verhält sich ein wenig wie ein Gletscher: Egal ob man sich heute, morgen, nächsten Monat oder nächstes Jahr danach erkundigt, wie weit das Spiel fortgeschritten ist, wird es immer so aussehen, als habe sich nichts bewegt – aber es bewegt sich doch! Und jede Änderung wird sogar schriftlich in meinem Devlog dokumentiert.

Smart-Aim

Die neueste Work-In-Progress-Version 0.92 bringt einige nette, aber hauptsächlich experimentelle Spielereien mit, die ich unbedingt ausprobieren wollte. Letztmalig kündigte ich die Möglichkeit eines Aimbots (Smart-Aim) für den Spieler an. Diesen habe ich nun tatsächlich eingebaut. Mit per Menü aktiviertem Smart-Aim muss der Spieler nur noch grob in die Richtung eines Gegners zielen und die automatische Zielhilfe passt den Schusswinkel bis zu einem gewissen Grad so an, dass ein Treffer garantiert ist. Wenn kein Treffer garantiert werden kann, greift die Zielhilfe dagegen nicht ein. Die Arbeit am im letzten Update-Artikel erwähnten Weapon-Interface ist vollständig abgeschlossen. Zusätzlich lassen sich nun ganz einfach per Mausrad die verschiedenen Waffen des Spielers durchschalten und im Spiel verwenden. Das muss nicht bedeuten, dass der Spieler im Endeffekt mehrere Waffen besitzt, aber er könnte theoretisch.

Eingabequellen

Nach dieser kleinen großen Baustelle eröffnete ich dann gleich die nächste, und so überarbeitete ich skrupellos die komplette Spielsteuerung. Meine Idee war die Entwicklung eines flexiblen InputReceiver-Interfaces, das es ermöglichen sollte, verschiedene Eingabequellen für Spieler-Inputs an die Spielerschiffe anzuschließen. Dies wird spätestens im Multiplayer-Modus ein sehr wichtiges Thema. Die konkreten InputReceiver-Implementierungen erzeugen getaktet (pro Update) einzelne „ControlActions“, also gekapselte Eingabedaten, die auf eine abstrahierte Maus und Tastatur anwendbar sind, um ein Spielerschiff und somit die Spielwelt zu beeinflussen. Genauer gesagt habe ich nun einen MouseInputReceiver, der (wie der Name schon sagt) direkt die Maus (und Tastatur) anzapft. Aber zusätzlich habe ich auch einen RemoteInputReceiver, der Benutzereingaben von anderen Mitspielern aus dem Netzwerk empfängt, einen ReplayInputReceiver, der Benutzereingaben aus einer persistierten Datenquelle einlesen und ausführen kann, und zuletzt einen BotInputReceiver, der in Echtzeit künstliche Benutzereingaben anhand eines vorgegebenen Regelwerks erzeugen kann. Moment … Replays? Bots?

Bots

Als ich über die technischen Möglichkeiten meiner dynamischen Gegner-KI, des fertigen Aimbots und der InputReceiver-Logik sinnierte, ist mir plötzlich aufgefallen, dass ich im Grunde schon die halbe Arbeit erledigt hatte, die nötig wäre, um einen kompletten Spieler-Bot zu entwickeln. Diese Idee hatte ich eigentlich schon zu Beginn des Projektes für Skirmish-Multiplayer-Spiele, wenn mal nicht genügend menschliche Mitspieler zur Verfügung stünden. Außerdem würde ein funktionaler Spieler-Bot mir die Arbeit beim Testen erleichtern, da ich nicht mehr gleichzeitig spielen und debuggen müsste, sondern mich auf das Wesentliche konzentrieren könnte. Allerdings fiel mir beim Implementieren auf, dass es wohl doch nicht so ein Spaziergang werden würde, wie ich zunächst dachte. Im Gegensatz zur Gegner-KI, die die Raumschiffe immer direkt steuern kann (drehen, beschleunigen, bremsen, schießen…), darf ein Spieler-Bot im Grunde nur Maus und Tastatur übernehmen, das Spieler-Raumschiff also indirekt mit simulierten Mausbewegungen und Mausklicks steuern. Mit Hilfe der InputReceiver war dies nun zumindest technisch kein Problem mehr. Aber natürlich musste die Logik dafür trotzdem erstmal geschrieben werden.

Nach einigen Tagen des Grübelns, Ausprobierens und auch Scheiterns hatte ich einen halbwegs glaubhaften Bot entwickelt, der in jedem Level losfliegen, bei Bedarf nützliche Powerups einsammeln, Gegner und Asteroiden beschießen und auch ins Ziel fliegen kann. Um das zu bewerkstelligen darf er im Grunde nur die Maus im Kreis bewegen, sowie die linke und die rechte Maustaste drücken. Er kann leider noch nicht ausweichen und ist auch sonst relativ blind und stur, aber er zielt immerhin ganz gut und gewinnt daher auch fast immer. Das Potenzial für Verbesserungen ist dafür enorm, z.B. müsste er verlorene Waren wieder einsammeln. Meine finalen Bemühungen, die Bewegungen des Bots realistischer zu machen, waren begrenzt erfolgreich. Dennoch ist das Ergebnis aus meiner Sicht schon beachtlich. Nebenbei fand ich eine deutlich bessere Methode, einen Abfangvektor zu einem beweglichen Zielobjekt im Level zu berechnen. Diese Methode habe ich mir sogar vorgemerkt, um sie bei der Gegner-KI einzubauen, als ich feststellte, dass das Ergebnis exakt genauso aussieht wie bei etlichen Gegnern im Originalspiel. Endlich war ich auf der richtigen Fährte, nachdem ich jahrelang keine Ahnung hatte, wieso meine KI sich immer irgendwie anders bewegt als im Original.

Replays

Gleich der nächste Knüller: Mit der Idee der InputReceiver konnte ich endlich Benutzereingaben im Spiel aufzeichnen und theoretisch jederzeit erneut ausführen. Fürs Aufzeichnen gibt es im Spiel nun einen ReplayRecorder, der die ControlActions pro Update ableitet und in einem Replay-Objekt speichert. Am Ende wird das Replay-„Tape“ finalisiert und kann im Speicher gehalten oder komprimiert in eine Datei gespeichert werden. Ein ReplayInputReceiver kann dieses Objekt wieder als Eingabequelle für den Spieler wählen. Vereinfacht gesagt, das komplette Gameplay eines Levels lässt sich aufnehmen und anschließend nochmal exakt identisch als Replay abspielen. Da die Aufzeichnung natürlich kein Film ist, sondern nur ein Protokoll aller Benutzereingaben auf einer Zeitachse, ist der Speicherbedarf geringer, aber das Replay anfällig für Veränderungen. Was ich damit meine, wird jetzt deutlich, wenn ich die nächste kleine große Baustelle erwähne, an der ich seit einigen Tagen arbeite.

Die Replays lassen sich zwar endlich perfekt aufnehmen und auch wieder abspielen, aber sie ergeben danach keinen Sinn mehr: Der Replay-Spieler macht zwar alles exakt so, wie das Tape es vorgibt, aber die Spielwelt eben nicht. Das Level sieht anders aus, die Gegner verhalten sich anders, nichts ist da wo es sein sollte. Folglich kracht der Spieler plötzlich wie ein Betrunkener überall dagegen, schießt meilenweit an den Gegnern vorbei, fliegt in die völlig falsche Richtung, und ist quasi nach wenigen Sekunden Gameover. Das Gameplay verlässt sich an sehr vielen Stellen auf Zufallszahlen, und auch die Levelgenerierung ist zufällig. Daran ist im Grunde gar nichts auszusetzen, da Spielentwicklung ganz ohne Zufallsgeneratoren kaum möglich wäre. Was mir nur noch fehlte, war der programmweite Einsatz von reproduzierbaren Zufallszahlen, die auf Basis eines gespeicherten Seeds funktionierten. Gleicher Seed bedeutete dann: Gleiches Level, gleiche Gegner, gleiches Verhalten, alles exakt gleich. Die Spielwelt musste vollständig deterministisch zufällig werden, und die Replays müssten den Seed speichern, der dann die Grundlage für das Replay bildet. Diese Umstellung ist leider sehr aufwändig und umfasst das Umschreiben vieler Bausteine der Levelgenerierung.

Spielereien

Nach diesem schwergewichtigen Problem möchte ich zum Schluss noch kleinere Physikspielereien erwähnen, die ich ins Remake eingebaut habe. Als kleine Option im Enhanced-Modus lassen sich die Stationen der Piraten quasi kugelsicher schalten, so dass die Geschosse des Spielers daran mit passendem Soundeffekt abprallen. Hierzu musste ich meinen Bounce-Code umschreiben, denn der sah bisher nur Kollisionen zwischen zwei beweglichen Objekten vor. Im Spezialfall einer Kollision zwischen einem unbeweglichen und einem beweglichen Objekt durfte eine Reaktion logischerweise nur auf das bewegliche Objekt erfolgen. Das Feuern auf die kugelsichere Station sieht schon recht witzig aus und die abgelenkten Kugeln fliegen einem um die Ohren. Ob das im fertigen Spiel Verwendung findet, steht natürlich auf einem anderen Blatt, aber es schadet nicht, wenn die Funktion schonmal eingebaut ist. Achja, eine weitere Option erlaubt jetzt das Zerstören der Stationen. Ich wollte einmal testen wie es aussehen könnte, wenn im Spiel ein großes Objekt gesprengt wird, und dabei kam diese kleine Funktion heraus. Es werden Unmengen an Explosionspartikeln erzeugt und die Station verabschiedet sich mit einem lauten Knall. Wie gesagt, natürlich nur eine Spielerei. Ergibt auch keinen Sinn, besonders dann nicht, wenn es die Zielstation war.

Eine letzte neue Option im Optionsmenü ist die Wahl der Spielgeschwindigkeit. Hierdurch lässt sich das Spiel mittlerweile erheblich verlangsamen. Für den Anfang kann man die Updaterate daher auf 1/2, 1/4, 1/8 oder 1/24 stellen. Dies ist allerdings nicht nur sinnlose Spielerei, sondern die erste Vorbereitung auf einen Rewrite der Spielengine, der früher oder später dringend nötig sein wird: Das völlige Entkoppeln von Update- und Drawrates, und die stufenlose Wahl der Spielgeschwindigkeit. Es muss also möglich sein, die Spielgeschwindigkeit z.B. drastisch zu reduzieren, aber trotzdem alle Spielobjekte weiter mit bis zu 72 fps flüssig zu bewegen. Denn aktuell bedeutet eine reduzierte Geschwindigkeit nur, dass die Spielwelt weniger oft aktualisiert wird, und dann spielt die Framerate eben keine Rolle. Das Spiel sieht dann leider nicht nach Zeitlupe aus, sondern nach Diashow.

Meilenstein

Es gibt da zwar noch so ein Thema, einen wichtigen Meilenstein, den ich unbedingt erläutern möchte, aber das werde ich demnächst in einem separaten Artikel abhandeln, da es sehr umfangreich wird.

Ein Besucher meines Blogs hat mir vor einigen Wochen die absolut berechtigte Frage gestellt, ob die Entwicklung an meinem kleinen SPACOLA-Remake-Projekt denn inzwischen eingestellt wurde. Ich möchte diese Gelegenheit für ein ehrlich gemeintes Lebenszeichen und wieder einmal ein wenig Selbstkritik nutzen. Ich bin zudem dankbar für jedes bisschen Aufmerksamkeit, das mir immer wieder einzelne Leser des Blogs schenken, die sich für das Projekt interessieren. Das zeigt mir zumindest, dass ich die Arbeit nicht alleine für mich mache (obwohl das natürlich nach wie vor der Hauptgrund ist).

Die gute Nachricht: Nein, die Entwicklung an dem Spiel ist definitiv NICHT eingestellt. Ja, ich arbeite Monat für Monat daran weiter. The show must go on.
Die schlechte Nachricht: Ich arbeite sehr langsam, und meine Motivation schwankt leider von Woche zu Woche. Es tut mir leid, so ist es eben. Manchmal hänge ich mich so richtig rein und kann mich kaum bremsen. Manchmal kriege ich aber auch wochenlang mal so überhaupt nichts gebacken. Das ärgert mich dann meist selbst, so dass ich versuche, Strategien zu entwickeln, um wieder in das Thema hineinzufinden.

Ein Release von SPACOLA ECLIPSE liegt also eher in ferner als in naher Zukunft. Das mag enttäuschend sein, aber das heißt nicht, dass ich aufhöre. Und es heißt vor allem nicht, dass ich zwischenzeitlich nichts gemacht habe, denn kleine Fortschritte gibt es ständig. Das möchte ich heute mit diesem Beitrag zeigen. Vor allem die Farbversion des Remakes hat in den letzten Wochen erneut Fahrt aufgenommen. Und da Bilder bekanntlich mehr sagen als 1000 Worte, möchte ich einfach mal drei aktuelle Impressionen der neuesten Work-In-Progress-Version 0.85 zeigen.

Work-In-Progress-Version 0.85 im verbesserten „SPACOLOR“-Spielmodus

Ich habe versucht, einen Screenshot zu erstellen von einer möglichst hektischen und actionhaltigen Szene, auf der viele Elemente gleichzeitig zu sehen sind. Das komplette HUD ist quasi fertig. Wie zu erkennen ist, sind die Stationsgeschütze noch nicht koloriert, aber vieles andere schon. Außerdem sorgen die vielen Explosions- und Antriebs-Partikel schon für eine Menge Bewegung und Gewusel auf dem Bildschirm. Um meinen neuen Lenkraketen-Code zu testen, habe ich die Stationsgeschütze so eingestellt, dass sie eine größere Anzahl Lenkraketen auf den Spieler abfeuern, anstelle kleinerer Geschosse. Die gefährlichen Stationsgeschütze eingeschlossen, sind hier immerhin drei Gegnertypen zu sehen, die allesamt Jagd auf den Spieler machen. Der kann in der Szene allerdings mit seinem Schutzschild (noch) dagegen halten kann. Mehrere Lenkraketen werden demnächst von allen Seiten einschlagen, was die Situation sicherlich nicht verbessert.

Level-Auswahl-Bildschirm vor jeder Runde

Am Anfang des Spiels kann man stets nur ein einziges Level auswählen. Die schwierigeren Sonnensysteme werden dann nach und nach zugänglich, sobald man in der Galaxie ein wenig Geld verdient hat. Das gesamte Spiel mit allen Menüs ist inzwischen in Farbe verfügbar, darunter natürlich auch die Schriftarten, die Mauszeiger, das Level-Auswahl-Panel, und alle Schaltflächen. Am unteren Rand analog zur TOS-Demo des Ur-SPACOLA prangt ein kleiner Hinweis bezüglich der Unfertigkeit des Remakes. Authentizität und Originaltreue ist bei der Entwicklung immer ein entscheidendes Grundprinzip. Jeder einzelne Pixel muss immer genau dort sitzen, wo er im Original auch platziert worden wäre. Hierzu nehme ich mir viel Zeit, um Screenshots zu vergleichen und Abstände zu messen.

Künstlerische Freiheiten nehme ich mir ausschließlich dort, wo sie absolut sinnvoll und vor allem nötig sind. So ist zum Beispiel der gesamte Metallic-Look der Farboberfläche eine alte Idee von mir, die ich schließlich möglichst perfekt mit dem Original-Design in Einklang bringen wollte. Selbst den Farbverlauf des Remake-Schriftzugs habe ich nicht einfach irgendwie aus dem Ärmel geschüttelt, sondern es basiert auf einem Design von der alten Dongleware-Webseite, wo es bereits eine frühe eingefärbte Fassung zu bewundern gab.

Der gute alte „SPACoLASSIC“-Spielmodus mit handgepixelter Monochromgrafik

Selbstverständlich lässt sich das Spiel auch komplett in der Originalgrafik spielen, bei der alles soweit unangetastet bleibt (verständlicherweise bis auf Details im Intro). Für Fans und Puristen gibt es dann „nur“ Monochrom-Sprites bei limitierten 36 Bildern pro Sekunde, und keinerlei Partikeleffekte oder sonstige neue Spielereien. Das Gameplay bleibt allerdings identisch.

Wer wissen möchte, an welchen Details ich mich da eigentlich so aufhalte, der möge gerne weiterlesen: Im Remake gibt es inzwischen ein Weapon-Interface, das es allen Schiffen im Spiel (Spieler, Mitspieler und Feinde) dynamisch ermöglicht, quasi auf Befehl eine andere Waffe zu aktivieren, seien es die Spieler-Standardwaffe, Lenkraketen, Laserwaffen, zwei Arten von Turret-Waffen, Minen, oder beispielsweise schlagkräftige Kanonenkugeln. Darüber hinaus habe ich eine AimHelper-Klasse geschrieben, die alle im Spiel bekannten Arten von Anvisier-Techniken der Gegner wiederverwendbar implementiert und mühelos auf alle möglichen Spielobjekte anwenden lässt. Wie präzise oder wie schlecht ein feindliches Schiff zielt, kann ich so dynamisch ohne Quellcode-Änderungen bestimmen. Damit kann sogar der Spieler eine Art „Aimbot“ bekommen, wenn man denn möchte. Das wäre jedenfalls eine Idee für ein zusätzliches Powerup.

Im Dezember habe ich übrigens das SPACOLA-Codebuch abgetippt. Nein, nicht die Koordinaten. Die gibt es schon in digitaler Form und sind im Remake auch zu 100% enthalten. Die Rede ist von den Powerups, also die Extras, die als kleine Symbole neben den Koordinaten im Buch abgedruckt sind. Mein innerer Perfektionist wollte partout nicht damit leben, dass dieser Teil des „Sternenatlas“ nicht im Remake nutzbar sein wird. Also habe ich angefangen, die Extras mühsam abzutippen, wo sich allerdings nach zwei Buchseiten bereits zeigte, dass ich so niemals fertig werden würde. Also habe ich mir ein kleines Progrämmchen geschrieben, das mir die Eingabe der Zeichen erleichtert: Ich musste quasi nur noch das jeweils passende Symbol anklicken und das Ergebnis wird direkt in eine CSV-Datei geschrieben.

Aber im Endeffekt bleibt alles Handarbeit. Es geht hier schließlich um 154 Buchseiten á 3 Blöcke pro Seite á 64 Symbole. Summa summarum sind das 29568 Symbole. Also 29568 Netto-Mausklicks. Und dann ist da noch gar nicht eingerechnet, dass ich mich recht oft verklickt oder verlesen habe, und einige Seiten im Buch von so schlechter Druckqualität sind, dass man praktisch nur noch raten kann, was da steht. Zum Glück gibt es eine Methode um zu validieren, ob die Eingabe stimmt, sonst wär die Fehlerquote einfach zu hoch. Und ja, es hat einige Tage gedauert, aber am Ende war ich mit allem fertig. Somit kann ich nun stolz behaupten, dass das Remake nicht nur sämtliche Koordinatenangaben akkurat wiederverwendet, die im Sternenatlas abgedruckt sind, sondern auch alle Powerups in die Levelkarten einbindet, so wie es im Originalspiel war.

Und wann wird SPACOLA ECLIPSE endlich fertig … oder wenigstens mal spielbar? Tja, keine Ahnung. „When it’s done“ ist ja mittlerweile ein geflügeltes Wort in der Spielebranche, das immer wieder gerne gewählt wird und auch sehr gut passt. Ich weiß nicht wann es fertig wird. Aber ich weiß, dass ich weitermache. Und so langsam fügen sich die vielen kleinen Puzzleteile immerhin zu einem erkennbaren Bild zusammen. Vielleicht dauert es gar nicht mehr so lange, bis das erste komplett spielbare Level veröffentlicht wird.

Linux-Support

Palim palim! Der unregelmäßige SPACOLA-Remake Fortschrittsbericht ist da! Och, keine Sorge, viel Fortschritt gibts nicht. Aber es gibt immerhin was zu sehen. In den vergangenen Monaten habe ich weitestgehend unter Linux Mint weiterentwickelt, und leider ging auch ein nicht unwesentlicher Teil der Zeit dafür drauf, Probleme zu beheben, die das Spiel nur unter Linux hatte. Zum Beispiel habe ich es lange Zeit nicht hinbekommen, dass das GUI-Fenster sowohl unter Windows als auch unter Linux immer exakt die gewünschte Größe hat. Wenn es unter Linux gepasst hat, war es unter Windows falsch. Wenn ich es dann für Windows korrigiert habe, war die Linux-Version plötzlich wieder schief. Wenn das programmatische Resizing des Fensters endlich überall funktionierte, ging dafür die Menüleiste nirgends mehr. Habe ich eine Sache repariert, geht eine andere Funktion kaputt. Es war wie bei einem Teppich, bei dem man eine Unebenheit mit dem Fuß ausbessern will, die sich dann nur immer wieder woanders auftut. Da soll mir nochmal einer sagen, Java sei wirklich plattformunabhängig. Swing ist es jedenfalls schonmal nicht. Ich habe viele graue Haare bekommen bis es endlich perfekt war. Die aktuelle Version funktioniert somit einwandfrei unter Windows und Linux.

Neue Artworks

In der Zwischenzeit habe ich viel mit neuen Artworks experimentiert und dabei kräftig mit GIMP gebastelt. Lange Zeit habe ich darüber gegrübelt, wie ich die Titelgrafiken designen soll, so dass sie sehr nahe am Original bleiben, und trotzdem viel Spielraum für eine Neuinterpretation im Sinne des Remakes erlauben. Mittlerweile habe ich ein mehr oder weniger einheitliches Design für den Fensterhintergrund, für den About-Dialog, für die Webseite und für den Splash-Screen beim Laden entworfen. Ja, das Remake hat jetzt einen eigenen Ladebildschirm, weil das Starten auf manchen Systemen doch schon mal die eine oder andere Sekunde länger dauern kann. Die Grafiken sind natürlich bei weitem nicht perfekt, aber ich glaube, man kann das erstmal so stehen lassen. Der Wiedererkennungswert ist schonmal ganz ordentlich.

Spiel laden und speichern

Die Funktionen zum Laden und Speichern der Spielstände sind jetzt endlich fertig. Genau wie im Original kann der Kaffee-Button genutzt werden, um den aktuellen Spielstand zu speichern. Zusätzlich gibt es außerdem die Möglichkeit, beliebig viele weitere Spielstände zu speichern und auch via Dateiauswahl wieder zu laden. Im Moment bezieht sich das Speichern jedoch nur auf den Zustand zwischen den Levels, nicht direkt IM Spiel. Ob eine solche Funktion noch nachgereicht wird, und ob das jemandem viel hilft, muss ich noch klären. Jedenfalls ist es klasse, dass man nun tatsächlich den Spielfortschritt in eine Datei persistieren und so jederzeit fortsetzen kann. Damit wäre ein wichtiger Punkt von meiner Todo-Liste gestrichen.

GEM-Schriftarten und Highscore-Liste

Die Remake-GUI verwendet jetzt konsequent drei verschiedene Original-TOS/GEM-Systemschriftarten, um so zusätzlichen Wiedererkennungswert zu generieren. Die Atari ST-Schriftarten erkennen Fans sofort. Nicht dass diese Schriftarten besonders hübsch oder gut lesbar wären, aber sie geben einem echten Nostalgiker doch schnell ein warmes Gefühl. Die Highscore-Liste wurde von mir deutlich erweitert. Zusätzlich wird nun der Highscore-Zeitstempel gespeichert, außerdem die Komplettierungsrate des Spiels in Prozent, damit man die Angaben besser vergleichen kann. Außerdem werden jetzt beliebig viele Einträge gespeichert. Im gerenderten Spiel selbst tauchen dann allerdings nur die ersten zehn Einträge auf, und dann auch nur deren Namen und Punktestand – die übrigen Werte werden einfach versteckt, um so nah beim Original zu bleiben wie möglich.

Post-Processing-Filter dank neuer Rendering-Methode

Besonders wenn man das Spiel auf Pixelverdoppelung stellt, also in der Auflösung 1280×800 spielen will, bremsen etwaige Post-Processing-Filter das Spiel leider so stark aus, dass es kaum noch Spaß machen kann. Zwar gibt es im Moment mit der Invertieren-Funktion nur einen einzigen Filter, aber ich wollte dort in Zukunft noch mehr Filter-Optionen anbieten, um den Look des Spiels den eigenen Bedürfnissen anzupassen. Nun, meine Idee war es, das Post-Processing immer nur auf die gerenderte Spielgrafik (in niedriger Auflösung) anzuwenden, und erst dann das Ergebnis hochzuskalieren. Würde ich erst hochskalieren und dann die Filter auf die hohe Auflösung anwenden, wäre das logischerweise viel langsamer. Leider machte dieser neue Ansatz es nötig, einige Teile des Renderings umzuschreiben, um die neue Reihenfolge der Arbeitsschritte zu ermöglichen. Zusätzlich implementierte ich eine Filterklasse, die es erlaubt, unbegrenzt viele verschiedene Filter ins Bild „einzuhängen“, um die Grafik zur Laufzeit jederzeit zu ändern. Der neue Code funktioniert wirklich erstaunlich schnell und schön flexibel. Die Änderungen haben sich gelohnt.

Neuer Anvisieren-Algorithmus für Geschütze

Man mag es kaum glauben, aber ich habe wirklich übermäßig viel Zeit in den Algorithmus für das Anvisieren der Geschütze investiert. Ich dachte ursprünglich, es genau richtig hinbekommen zu haben. Dann fiel mir jedoch beim Nachspielen des Originals auf, dass die Geschütze beim ST-Klassiker nie daneben feuern, egal wie schnell und egal wohin der Spieler sich bewegt. Das bedeutete, dass die Geschütze nicht nur den Winkel zum Spieler und dessen Bewegungsgeschwindigkeit in die Berechnung des Vektors einbeziehen, sondern bei bekannter eigener Geschossgeschwindigkeit auch den Abschusswinkel exakt so berechnen, dass die Geschosse den Spieler an einem unbekannten Punkt zielsicher treffen. Am Ende habe ich mir das Problem bestimmt ein dutzend Mal auf einem kartesischen Koordinatensystem skizziert und versucht herzuleiten, wie der Winkel berechnet wird. Ich wusste wie lang der Vektor sein dürfte, ich wusste nur nicht, wo er den anderen Vektor schneiden würde. Am Ende fand ich eine Lösung, indem ich den Spielervektor von der Position des Geschützes aus nahm, einen Kreis mit Radius der erlaubten verbleibenden Vektorlänge um diese neue Koordinate berechnete um die Schnittpunkte mit dem anderen Vektor zu finden. Der Vektor vom Geschütz zu diesen Schnittpunkten muss dann der Abschussvektor sein. Das ist dann zwar eine vergleichsweise teure Berechnung, aber sie funktioniert perfekt.

Levelgenerator-Verbesserungen

Den Levelgenerator habe ich wieder geringfügig verbessert. So funktionieren die Floodfilling-Methoden für Konfigurationen von Stationen, Powerups und schwarzen Löchern jetzt besser und erlauben auch die Übertragung von Parametern, wie aus dem Levelskript vorgegeben. Der Levelgenerator setzt nun korrekt die Deploy-Distanz für Gegner, die Deployment-Rate und die Anzahl gleichzeitig erlaubter Gegner. Außerdem habe ich eine Funktion eingebaut, die ich nur als „Shield-Powerup-Stacking“ bezeichnen kann, die mir im Original sehr merkwürdig vorkam. Ich bin mir immer noch nicht sicher, ob das ein Bug ist, oder ob es beabsichtigt war. Jedenfalls kann der Spieler seine Schutzschild-Option zeitlich deutlich verlängern, wenn er mit aktiviertem Schutzschild noch ein weiteres Schild-Powerup einsammelt. Ich müsste wohl auch noch prüfen, ob dieses „Feature“ in jeder Spacola-Version auftritt, oder nur in einer bestimmten. Jedenfalls ist das nun ebenfalls im Remake perfekt nachgebildet.

So, das waren wieder einige kleine Einblicke in die Entwicklung der vergangenen Monate. Ich bleibe am Ball und arbeite mich langsam voran. Der Quellcode umfasst inzwischen über 40.000 Zeilen und wächst stetig weiter.

Okay, ich habe wieder einmal sämtliche mir selbst gesetzten Deadlines verschlafen. Das Remake wurde leider doch nicht zum 25-jährigen Jubiläum fertig, und wird es vermutlich auch noch eine ganze Weile nicht. Scheiß drauf. Ich bin gleichzeitig Opfer meiner eigenen Faulheit und Penibilität geworden. Das Problem mit Arbeit nach der Arbeit ist, dass sie oftmals keinen Spaß macht, egal wie sehr einem das Zeug am Herzen liegt. Aber hey, ich habe Urlaub – Zeit für mehr Arbeit. Und das Wichtigste ist doch: Ich bin wieder dabei! Vor wenigen Tagen habe ich mit der Arbeit an der Version 0.60 begonnen.

Ich habe eine neue Spritebibliothek geschrieben, die sich um das Laden, Konvertieren und Verwalten der vielen kleinen Grafikdateien kümmert. Und diese Spritebibliothek kennt neuerdings auch jeweils die Monochrom- und Farbversion jeder einzelnen Grafik. Bisher waren dies verschiedene Klassen, die immer jeweils getrennt voneinander angepasst werden mussten, und auch der Wechsel von Monochrom nach Farbe hätte bisher viele Codeanpassungen erfordert. Nun wird es möglich, direkt im Client mit einem simplen Mausklick die Darstellung zu wechseln. SPACOLA Eclipse kann endlich richtig mit Farbe umgehen. Da aber noch weit über 90% der Sprites nur monochrom vorliegen, werde ich da irgendwann noch wahnsinnig viel Zeit investieren dürfen. Bisher gibt es nur vereinzelte Sprites in Farbe zu sehen.

Die Farbsprites haben aber noch keine Priorität. Zunächst muss der Classic-Modus fertiggestellt werden, und das ist nach wie vor nicht so einfach wie es klingt. Die Gegner-KI macht mir Sorgen, denn egal wie ich es anpacke, es verhält sich alles nie so ganz wie es sollte, oft scheitert es schon am Ansatz. Dafür habe ich erst zuletzt ein komplettes Explosions-Spriteset hinzugefügt, das mir bisher nicht aufgefallen ist. Es scheint also doch nicht so klar zu sein, dass ich inzwischen wirklich alles aus dem Spiel extrahiert habe. Und ich habe anhand eines Memory Dumps die Zuweisungen der Sounddateien korrigiert, also welcher Sound im Originalspiel welchen Dateinamen hatte. Bislang musste ich dazu raten, und scheinbar lag ich oft falsch. Immerhin konnte ich hier nun einige Fehler korrigieren und so manche Zuweisungen bestätigen, auch wenn es bei anderen Einträgen weiterhin beim Raten bleibt, da der Memory Dump nur eingeschränkt Aufschluss gibt, auf Grund der Art wie die Sounddateien im Original nachgeladen werden können.

Ich hoffe ich werde noch diesen Dezember einige vorzeigbare Fortschritte vermelden können. Kleine Schritte, Tag für Tag. Macht es die Sache besser oder schlimmer, wenn ich jetzt verkünde, dass das Remake in jedem Fall zum 30. Jubiläum im Jahr 2021 fertig sein wird? Hey, wieso werft ihr denn jetzt mit überreifen Tomaten und faulen Eiern nach mir? Okay, okay, ich fang ja schon an…