CrossCode hat sich seit seiner Veröffentlichung als ein herausragendes Beispiel für sorgfältige und durchdachte Spielentwicklung etabliert. Die Architektur des Spiels ist ein Spitzenbeispiel dafür, wie ein Entwicklerteam ein minimalistisches Framework so anpassen und erweitern kann, dass es den komplexen Anforderungen eines modernen Rollenspiels gerecht wird. In diesem Artikel werfen wir einen detaillierten Blick auf die Architektur von CrossCode und die fundamentalen Prinzipien, die hinter ihrem Design stehen. Ursprung und Herausforderungen von impact.js CrossCode basiert auf impact.
js, einer Engine, die speziell für HTML5-Spiele entwickelt wurde. impact.js ist bekannt für seine schlanke und minimalistische Herangehensweise, die es Entwicklern ermöglicht, rasch funktionierende Spiele zu erstellen. Die Engine liefert eine Basisausstattung, mit der man schnell startklar ist, ohne dass eine Vielzahl vorgefertigter Features die Flexibilität einschränkt. Der Nachteil dieser minimalistischen Struktur von impact.
js zeigt sich jedoch bei größeren Projekten mit komplexeren Anforderungen. impact.js ist für 2D-Jump’n’Run-Spiele optimiert, weshalb für ein Top-Down-Rollenspiel wie CrossCode weitreichende Anpassungen notwendig wurden. Die ursprüngliche Struktur der Engine ist einfach gehalten mit begrenzten modularen Erweiterungsmöglichkeiten und einer engen Verbindung von Spielcode und Leveldaten, was bei ambitionierten Projekten die Wartbarkeit und Erweiterbarkeit erschwert. Um diesen Herausforderungen zu begegnen, entschied sich das CrossCode-Entwicklerteam, impact.
js nicht nur zu nutzen, sondern tiefgreifend zu modifizieren. Ziel war es, eine Architektur zu schaffen, die modular, wartbar und auf hohe Anforderungen ausgelegt ist, ohne die Flexibilität und Leistung zu beeinträchtigen. Die traditionelle Struktur von impact.js Ein Standardprojekt mit impact.js verfügt über eine klare Ordnerstruktur, die den Spielcode, die Entitäten, Level, Medien und die Engine selbst trennt.
So finden sich beispielsweise die Spielentitäten in einem Ordner namens entities, die Levels in einem Level-Ordner und die Medien in einem separaten Medien-Ordner. Die Trennung der verschiedenen Komponenten ist vorhanden, aber hinsichtlich Modularität und Trennung von Code und Daten weist sie Schwachstellen auf. Besonders problematisch ist die Verknüpfung von Leveldaten mit JavaScript-Modulen. Dies führt dazu, dass sämtliche Levelinformationen bereits zu Spielstart geladen werden müssen, was bei kleinen Spielen effektiv sein kann, für größere Projekte wie CrossCode aber unpraktisch ist. Das Laden sämtlicher Leveldaten im Voraus führt zu längeren Ladezeiten und einem massiv erhöhten Speicherbedarf, was das Spielerlebnis beeinträchtigen kann.
Ein weiterer Schwachpunkt bei impact.js liegt im Fehlen eines robusten Systems zur modularen Erweiterung des Codes. Neue Features oder Entitäten erfordern oftmals das direkte Verändern von Hauptdateien wie main.js, was die Codebasis schnell unübersichtlich und schwer wartbar macht. Für kleinere Spiele oder Prototypen mag das akzeptabel sein, bei einem umfangreichen Rollenspiel wie CrossCode ist ein solcher Ansatz untragbar.
Die wegweisenden Änderungen in CrossCode Das Entwicklerteam von CrossCode konzipierte daher eine neuartige Architektur, die genau diese Schwächen adressiert. Die wichtigste Änderung ist die Einführung eines modularen Systems für die Erweiterung des Spiels. Statt alle Entitäten zentral in einem Ordner zu speichern, werden diese nun in sogenannten Features organisiert. Diese Features sind eigenständige Module, die Funktionen bündeln und gleichzeitig die Wiederverwendbarkeit in anderen Spielen sicherstellen. So sind beispielsweise Camera- oder GUI-Elemente eigene Features, die unabhängig voneinander in verschiedene Projekte eingebunden werden können.
Ein weiterer bedeutender Fortschritt zeigt sich in der Trennung von Spieldaten und Code. Während impact.js Leveldaten noch als JavaScript-Module integriert, nutzt CrossCode ein eigenständiges Datenverzeichnis für JSON-Dateien, die Levelinformationen, Animationen, Effekte und weitere nicht-binäres Spieldaten enthalten. Diese JSON-Daten werden asynchron geladen — was bedeutet, dass sie erst dann geladen werden, wenn sie im Spiel tatsächlich benötigt werden. Dies verringert die Anfangsladezeit drastisch und ermöglicht eine flexible Handhabung selbst großer Welten mit hunderten von Karten.
Diese Trennung und Modularisierung hat mehrere Vorteile. Zum einen leistet sie einen wichtigen Beitrag zur Skalierbarkeit des Spiels, ohne dass das Team Gefahr läuft, mit dem Codechaos konfrontiert zu werden. Gleichzeitig ermöglicht sie eine einfachere Wartung und Weiterentwicklung der Engine, da neue Module klar abgegrenzt und unabhängig voneinander entwickelt, getestet und aktualisiert werden können. Designprinzipien, die das Rückgrat von CrossCode bilden Das Architekturekonzept von CrossCode lässt sich mit zwei Prinzipien zusammenfassen, die eng miteinander verknüpft sind. Erstens: JSON-Daten sollten bevorzugt werden, um Codegröße und Komplexität zu reduzieren.
Anstatt für jeden Gegner oder jedes Objekt eine eigene Entity zu schreiben, verwendet CrossCode konfigurierbare Basis-Entities, die mit unterschiedlichen JSON-Daten gefüttert werden. Dieses Vorgehen erlaubt es, zahlreiche Variationen bei Gegnern oder Spielobjekten zu erzeugen, ohne dass das Codevolumen exponentiell ansteigt. Das Resultat ist eine übersichtliche und wartbare Codebasis, welche die Entwicklung effizienter macht. Zweitens: Erweiterungen sollten immer als Features implementiert werden, statt zentrale Dateien wie main.js immer wieder zu überladen.
Dadurch entstehen klar abgegrenzte Module, die sich problemlos wiederverwenden oder in andere Projekte übertragen lassen. CrossCode selbst hält main.js mit rund 290 Zeilen äußerst schlank und verwendet diese vor allem für grundlegende Initialisierungen, Debugging oder kleinere Hacks zum Testen von neuen Komponenten. Diese Herangehensweise fördert nicht nur eine gesunde Codebasis, sondern erlaubt dem Entwicklerteam auch, mehrere Projekte parallellaufen zu lassen und Bausteine einfach auszutauschen oder anzupassen. Für eine Indie-Entwicklung mit einem kleinen Team und begrenzten Ressourcen ist dies eine enorme Erleichterung und hilft, die Qualität des Spiels auf einem konstant hohen Niveau zu halten.
Asynchrone Datenverwaltung und deren Bedeutung Ein weiteres zentrales Element der CrossCode-Architektur ist die Verwendung von asynchronen Ladevorgängen. Während impact.js alle Leveldaten und Code bereits zu Spielstart vollständig lädt, bietet CrossCode dank der Nutzung von JSON-Assets und modifizierter Lade-Logik die Möglichkeit, Daten dynamisch beim Übergang zwischen Karten oder Spielszenen zu laden. Das reduziert nicht nur die Ladezeiten beim Spielstart, sondern entlastet auch den Arbeitsspeicher. Dieses Konzept ist besonders wichtig für Rollenspiele, die oft umfangreiche Welten mit zahlreichen Levels enthalten.
CrossCode konnte so eine flüssige Spielerfahrung gewährleisten, bei der große Welten nicht zum Flaschenhals werden. Zudem erlaubt die Datenstruktur des Spiels eine einfache Pflege und Anpassung der Inhalte — Leveldesigner können beispielsweise an den JSON-Karten arbeiten, ohne den Programmiercode anzupassen. Die Rolle der Features im Detail Ein zentrales Element der Architektur ist die klare Aufteilung zwischen wiederverwendbaren Feature-Modulen und spiel-spezifischen Erweiterungen. CrossCode nutzt zwei Namensräume: ig für allgemeine, enginespezifische Features und sc für spieleigene Features. So wird das Grundgerüst von impact.
js um nützliche Funktionalitäten erweitert, die sich in anderen Projekten ebenfalls einsetzen lassen, während sc alle Controls, Gegnermechaniken, Puzzle-Objekte und Gameplay-Logik enthält, die ausschließlich für CrossCode relevant sind. Diese Trennung erhöht nicht nur die Übersichtlichkeit, sondern ermöglicht auch Teammitglieder, gezielt an einzelnen Modulen zu arbeiten, ohne die gesamte Codebasis beachten zu müssen. Dadurch verbessert sich die Effizienz und die Qualitätssicherung kann präziser erfolgen. Ein Blick in die Zukunft mit modularen GameAddons In Postreihe über die Architektur von CrossCode wurde angekündigt, neben Features auch GameAddons als weitere Möglichkeit zur Modularisierung zu integrieren. Diese Addons sollen es erlauben, zusätzliche Spielinhalte oder Mechaniken flexibel zu ergänzen, ohne die Hauptstruktur zu beeinflussen.
Damit könnte CrossCode auf lange Sicht noch besser skalieren und neue Inhalte schneller ausgerollt werden. Ausblick und Bedeutung für die Spieleentwicklung Die Architektur von CrossCode zeigt exemplarisch, wie ein umfangreiches Spielprojekt von Grund auf richtig strukturiert wird. Die Kombination aus modularen Features, asynchronen JSON-Daten und einer bewussten Trennung von Code und Assets führt zu einem flexiblen System, das sich hervorragend an die komplexen Anforderungen moderner Rollenspiele anpasst. Diese Vorgehensweise ist nicht nur für CrossCode selbst ein großer Gewinn, sondern liefert wertvolle Erkenntnisse für die Programmierung von Spielen im Allgemeinen. Entwickler, die mit ähnlichen minimalistischen Engines arbeiten, können von CrossCode lernen, wie sich solch eine Engine sinnvoll erweitern lässt.
Insbesondere der Mut, die Engine tiefgreifend anzupassen und eigene Prinzipien zu implementieren, hebt CrossCode von vielen anderen Projekten ab. Zudem verdeutlicht die Architektur die Wichtigkeit von sauberer Modularität, Wiederverwendbarkeit und der Trennung von Daten und Code. Diese Prinzipien sind heutzutage unverzichtbar, um Spiele mit wachsendem Umfang und Komplexität handhabbar zu machen und weiterzuentwickeln. Abschließend lässt sich festhalten, dass CrossCode nicht nur inhaltlich, sondern auch technisch Maßstäbe setzt. Die Architektur des Spiels verbindet auf innovative Weise Minimalismus, Modularität und Performance und stellt somit ein herausragendes Beispiel für professionelle Spieleentwicklung im Indie-Bereich dar.
Für Entwickler und Interessierte lohnt es sich, diese Architektur genau zu studieren und daraus wertvolle Schlüsse für eigene Projekte zu ziehen.