Der Betreiber eines Roleplay-Servers für RedM, den Mehrspieler-Rahmen für Red Dead Redemption 2, hat mich mit einem neuen Ladebildschirm beauftragt. Ein RedM-Server zeigt beim Verbinden einen Ladebildschirm, und der ist eine gewöhnliche HTML-Seite. Der Kunde wollte dort seine Figuren sehen, die atmen, blinzeln und der Maus nachschauen, statt eines Standbilds mit Fortschrittsbalken. Was ich dafür suchte, war eine Spine-Alternative mit drei Eigenschaften, und ich habe keine gefunden.
Die erste: Die Seite läuft im eingebauten Browser von RedM, und der ist ein Chromium 103 aus dem Jahr 2022. Kein :has(), keine CSS-Verschachtelung, kein oklch(). Die zweite: Die Auslieferung ist ein Ordner, den ich in die Server-Ressourcen kopiere. Kein Build, keine Abhängigkeiten, ein <script>-Tag, Bilder und eine JSON-Datei. Die dritte: keine Lizenz, die am Umsatz hängt oder an einem Editor, den ich gar nicht benutzen will.
Also habe ich es selbst geschrieben. Das Ergebnis heißt idle-web-animation, steht unter MIT-Lizenz auf GitHub und beschreibt eine Figur als Stapel von Bildebenen plus eine Datei figure.json.
Warum nicht Spine, Live2D oder Godot
Die drei naheliegenden Werkzeuge habe ich mir angesehen, bevor ich angefangen habe. Die Tabelle steht so im README des Projekts; die Preise sind dort wörtlich notiert, Stand September 2026, laut Anbieter.
| Web-Laufzeit | Als Text schreibbar | Kosten | |
|---|---|---|---|
| Spine | spine-webgl, auch spine-canvas (2D-Canvas) | ja, das JSON-Skelettformat ist dokumentiert und editierbar, dazu eine Headless-CLI | 69 $ Essential / 379 $ Professional; Enterprise 2.499 $ + 379 $ je Nutzer ab 500.000 $ Umsatz. Die Laufzeitlizenz setzt eine Editor-Lizenz voraus. |
| Live2D Cubism | WebGL-Canvas | nein, .cmo3 und .moc3 sind Editor-Formate | Editor kostenlos, aber hart begrenzt (1 Textur, 100 ArtMeshes, 50 Deformer); PRO kostet bei jedem Umsatz. Die getrennte SDK-Veröffentlichungslizenz ist unter 10 Mio. Yen kostenlos. |
| Godot | WASM-Paket, mehrere zehn MB | ja, .tscn und .gd sind Klartext, --headless --script ist dokumentiert | kostenlos, MIT |
| idle-web-animation | DOM + CSS-Transforms | ja, eine JSON-Datei | kostenlos |
Der Grund für den Eigenbau ist die Laufzeit, nicht das Autoren-Werkzeug. Godot lässt sich vollständig aus Textdateien bauen, und das Skelett-JSON von Spine ist dokumentiert und von Hand editierbar; nur Live2D ist wirklich an seinen Editor gebunden.
Was keines der drei liefert, ist das eigentliche Ziel: DOM und CSS-Transforms in einem CEF von 2022, ausgeliefert als Ordner zum Kopieren. Spine und Live2D malen in ein Canvas, das sich mit dem Rest der Seite weder stylen noch mischen noch layouten lässt. Der Web-Export von Godot ist eine WASM-Laufzeit von mehreren zehn Megabyte, für einen Ladebildschirm, der sofort da sein muss. Spine kostet zusätzlich Geld, und die Laufzeitlizenz hängt am Besitz des Editors.
Wie eine Figur aufgebaut ist
Eine Figur ist ein Ordner mit Bildebenen und einer figure.json. Jede Ebene ist ein Bild in voller Leinwandgröße, etwa 1000 × 1000 Pixel, und sitzt genau dort, wo ihre Pixel sind. Der Kopf, der Poncho, die linke Hand, die offenen Augen: alles eigene Ebenen, übereinander gestapelt. Die JSON-Datei sagt, welche Ebene an welcher hängt, wo der Drehpunkt sitzt und welche Bewegungen sie trägt. So sieht eine Ebene in der Schema-Dokumentation aus, hier um drei Felder gekürzt:
{
"id": "hand",
"src": "layers/hand.webp",
"alt": "Hand",
"parent": "arm",
"pivot": [0.13, 0.78],
"depth": 0.7,
…
"motions": [
{ "type": "sway", "strength": 1.0, "period": 7.5, "degrees": 2.0 }
]
}
Die Hand hängt am Arm, dreht sich um einen Punkt bei 13 Prozent der Breite und 78 Prozent der Höhe ihrer Box und schwingt alle 7,5 Sekunden um zwei Grad. Bewegungen tragen Namen, keine Keyframes. Es gibt acht Blöcke: breathe, sway, blink, gaze, flipbook, glow, charge und drift. Mehrere Blöcke auf einer Ebene addieren sich, eine Hand kann also gleichzeitig schwingen und glimmen.
Die Engine dahinter, idle.js, hat 768 Zeilen ohne Leerzeilen. Ihr Kern ist eine Funktion solve(figure, t), die für einen Zeitpunkt t den Zustand aller Ebenen zurückgibt, immer denselben für dasselbe t, ohne Zufall und ohne gespeicherten Zustand. Deshalb lässt sich die Zeitleiste im Studio vor- und zurückschieben, deshalb ist der Contact Sheet exakt, und deshalb stimmen der DOM-Renderer für die Seite und der Canvas-Renderer für die Prüfbilder Bild für Bild überein.
Zwei Dinge muss der Autor gar nicht einstellen. Eine Kind-Ebene liest die Zeit etwas weiter zurück als ihr Elternteil, ein Saum hinkt der Schulter also von allein hinterher. Und jede Ebene verschiebt sich mit der Maus um ihre eigene Tiefe, so wird aus dem flachen Stapel ein Raum. Pedro, die Demo-Figur im Repo, besteht aus 35 solcher Ebenen.
Pedro, Demo-Figur, CC BY 4.0.
Das Studio: vom flachen Bild zur Figur
Die meisten Figuren beginnen als ein einziges flaches Bild, direkt aus der Zeichnung. Das Studio, eine HTML-Seite im Repo, nimmt es über „Flat image…“ entgegen und zeigt es als eine einzelne Ebene, die atmet. Das reicht, um zu sehen, ob die Figur lebt.
Dann kommt das Zerlegen. Kein Modell weiß von sich aus, dass ein Kragen zur Brust gehört und ein Riemen nicht. Ich male es stattdessen mit dem Pinsel: unter „Mark“ ein grober Klecks je Teil, jeder in einer eigenen Farbe, dazu ein Name. Der Name ist bereits das Rig: kopf bekommt einen Drehpunkt am Hals und eine Blickbewegung, arm eine Schulter und ein Schwingen. „Cut“ zerlegt das Bild entlang der Kleckse. Die Grenze verläuft dabei an den Kanten, die die Zeichnung schon hat, und folgt dem Pinselstrich nur grob.
Drehpunkte und Bewegungslinien einer Figur, im Studio markiert.
Was danach nicht stimmt, ziehe ich auf der Bühne zurecht. Ein Drehpunkt ist ein Gelenk, kein Mittelpunkt. Eine Hand, die sich um ihre eigene Mitte dreht, sieht aus wie ein rotierender Aufkleber, um den Ellbogen sieht sie aus wie ein Arm. Mit eingeschalteten Pivots zeichnet das Studio von jedem Gelenk eine Linie zum Gelenk des Elternteils, und ein falscher Parent fällt sofort auf.
Die Studio-Oberfläche von idle-web-animation mit Pedro, Demo-Figur, CC BY 4.0.
Ein Screenshot kann keine Bewegung beweisen. Dafür gibt es den Contact Sheet: 24 Bilder aus einem Fenster von 8 Sekunden in einem Bild.
Contact Sheet: alle Ebenen einer Figur auf einen Blick.
Ob ein Schnitt sauber ist, misst der Cut-Test. Er vergleicht die ausgeschnittenen Teile mit den Ebenen, aus denen ein Testbild vorher flachgerechnet wurde, als Intersection over Union. Die acht Teile der Testfigur baer kamen bei 24 Pixel Reichweite mit 0,9967 IoU zurück, in etwa zwei Sekunden. Eine größere Reichweite ist dabei keine bessere: Auf Marken, die 10 Pixel innerhalb der wahren Form gemalt waren, erreichte eine Reichweite von 15 Pixeln 0,95, eine von 90 Pixeln nur 0,65.
Cut-Test (IoU) zur Kontrolle sauber ausgeschnittener Ebenen.
Der Ladebildschirm für den RedM-Server
Die erste Anwendung ist der Ladebildschirm, für den das alles entstand. Er hat eine eigene Seite im Portfolio: Ladebildschirm für einen RedM-Roleplay-Server. Dort lässt sich der Bildschirm per Klick starten und ansehen.
Vier Figuren sind eingebaut: ein Priester, ein Mann mit wehendem Mantel, Pedro und eine Kriegerin. Beim Start wird eine zufällig gezogen, alle 25 Sekunden blendet die Seite zur nächsten über, und dieselbe Figur kommt nie zweimal hintereinander. Die Musik läuft über alle Wechsel hinweg durch, weil Player, Logo und Kino-Balken außerhalb der Szene liegen und nie neu erzeugt werden.
Das größte Problem war der Speicher. Eine Ebene kommt als volle Leinwand an, auch wenn nur eine Rauchwolke in der Ecke steht, und der Browser packt jedes Bild beim Anzeigen in voller Größe in rohe Pixel aus. Bei Pedro waren das 60 Bilder mal 1792 × 1000 Pixel mal 4 Byte, rund 410 MB für eine einzige Figur. Auf schwachen Rechnern wirft der Browser dann Bilder weg und packt sie kurz darauf neu aus, und genau in diesen Momenten stockt die Musik. Ein kleines Werkzeug schneidet deshalb jede Ebene auf den Bereich zu, in dem etwas zu sehen ist, und schreibt den Versatz als crop in die figure.json; der Player setzt das Bild wieder an dieselbe Stelle. Aus 547 MB wurden so 34 MB, und an der Bewegung ändert sich nichts.
Für wen sich das eignet
Wenn Sie einen Roleplay-Server auf FiveM oder RedM betreiben, ist der Ladebildschirm der erste Eindruck, den ein Spieler von Ihrem Server bekommt, und die Figuren dafür haben Sie meist schon: als Artwork, als Charakterbild, als Logo. Dasselbe gilt für Spiele-Studios, die auf ihrer Website einen Charakter zeigen wollen, ohne einen Video-Loop einzubetten, und für Agenturen, deren Kunde eine Maskottchen-Marke pflegt. Auch eine Messe- oder Produktseite trägt eine Figur, die dem Besucher nachschaut, solange die Bewegung klein bleibt.
Was ich dafür anbiete, ist der Teil, der Handarbeit bleibt: Ich bereite Ihre Figur auf, zerlege sie in Ebenen, setze Drehpunkte und Bewegungen und prüfe das Ergebnis mit Contact Sheet und Cut-Test. Danach baue ich die Figur in Ihre Website oder Ihren Ladebildschirm ein, mit dem Player aus dem Repo, ohne Laufzeitlizenz und ohne laufende Kosten. Wenn Sie eine Figur haben und wissen wollen, ob sie sich dafür eignet, schreiben Sie mir über die Kontaktseite.
Mitmachen
Der Code liegt auf GitHub unter broening/idle-web-animation, MIT-Lizenz. In der Live-Demo folgt Pedro der Maus. Das Studio läuft dort ebenfalls, allerdings nur lesend; Speichern braucht den kleinen Python-Server aus dem Repo auf dem eigenen Rechner. Fehlerberichte und Vorschläge nehme ich als Issues auf GitHub entgegen. Die Demo-Figur Pedro steht unter CC BY 4.0, eigene Figuren bleiben außerhalb des Repos.