All projects CurveExtreme · Write-up
Inputs, not positionsEingaben statt Positionen
CurveExtreme is our own curve game for the afternoon meeting, up to ten lines that never stop. Every page simulates the round itself on the server’s clock, only steering changes travel, and one that arrives late rewinds the round to where it belongs.CurveExtreme ist unser eigenes Kurvenspiel für das Nachmittags-Meeting, bis zu zehn Linien, die nie anhalten. Jede Seite simuliert die Runde selbst nach der Uhr des Servers, unterwegs sind nur Lenkwechsel, und einer, der zu spät ankommt, spult die Runde dorthin zurück, wo er hingehört.
curveextreme.ewolution.cloud Source
- Type
- Web appWeb-App
- Stack
- Svelte 5 · Node · WebSockets
- Year
- 2026
- Code
- Public on GitHubÖffentlich auf GitHub
A line that never stops
CurveExtreme is our own curve game for the afternoon meeting, in the line of Achtung, die Kurve!. Every player steers a line that never stops, left or right and nothing else. It leaves a short gap now and then, and touching any line or the wall ends your round, your own line included. When a curve crashes, everyone still driving scores a point, and the first to ten points per opponent, two points clear, wins the game. Teams play for round wins instead.
Whoever starts a game gets a room for up to ten curves with a four-letter code, a link and a QR code. There are no accounts: a name, a seal and a colour are enough, and a reload puts you back in the round. Up to four people can also share one computer, two keys each, in a mode that runs entirely in the page.
The steering, measured
The meeting used to play CurveCrash, so its steering is what this game had to match. CurveExtreme is a separate game of our own: its numbers were measured from the replays CurveCrash shows publicly, frame by frame, by tracking each line’s head and fitting its arcs and gaps. A line moves 90 units a second, a held key turns it on a circle of 35 units, 147 degrees a second, and it is 6.9 units wide. Gaps are 16 units long and come at random, 158 units of line apart on average. A round starts with 2.5 seconds standing still, an arrow showing each heading, then 2.5 seconds of moving without a line, and a decided round runs on for 4.65 seconds before the field clears.
Every number is data
None of those numbers is written into the game itself. They live in a feel profile, beside the 25 powerups and the modes, from Basic and None to GS++ at twice the speed, and Custom, where each powerup can be switched on or off. A powerup’s colour says who it hits: green ones you, red ones everyone else, blue ones the whole field. In the room, the host’s Tune panel shows every number of the feel as a dial with the measured value marked on it, applies a change from the next round, and can save the result as a profile for the next game.
Inputs, not positions
The network works the way many real-time games handle theirs, best known from fighting games: deterministic lockstep with rollback. CurveExtreme’s part is the implementation and its tuning. No page is ever told where a curve is. A round starts with its seed and the server’s time of its first frame, and every page simulates the whole round itself, on the server’s clock: the page measures that clock with a ping every few seconds, and the frame it is in always comes from the clock, never from counting. Only steering changes travel, one small message when a key goes down and one when it comes up, stamped with the frame and the thousandth of the frame it happened in. In a two-player test round, a page received 14 messages and sent 8.
Your own turn shows at once, because it goes into your page’s round before it leaves. Another player’s arrives a moment later; if its frame has already been drawn, the page goes back to a snapshot from before it and simulates forward again, which ends exactly where it would have if the turn had been there all along. Anyone just watching sees the game 200 milliseconds behind, so it never jumps.
The server referees
A Node server without dependencies runs the same round 150 milliseconds behind the clock. It takes a turn whose frame it hasn’t reached yet and passes it on to everyone else; a turn that comes later than that is refused, and the page takes it back and sends what the player is holding now. The server decides who’s out when two screens disagree, and it keeps the points, the rounds, the teams and the colours. Getting into a room takes two steps: a seat is reserved over HTTP, and the room’s WebSocket opens with it, carrying compact binary messages. Someone joining in the middle of a round gets its start and every turn so far, and simulates it up to the present. The host can also take a player out of the room.
The same bits on every screen
For every page to draw the same game, every page has to compute the same numbers, to the last bit. JavaScript’s sine and cosine may differ in that last bit between Chrome and Safari, and here a last bit can decide whether a line slips through a gap or crashes. So the game computes its own sine and cosine from addition, subtraction, multiplication and division alone, compares distances without square roots, and takes all of its randomness from the round’s seed. To check it, 24 ten-player rounds with every powerup were played in Node and in Safari’s engine and compared: they ended identically. The tests also replay rounds with turns arriving late, by a frame or by almost two seconds, and check that every round still ends in the same state.
Classic black
The field is black inside a thin white line, and the lines are flat with square ends, so the curves and the powerup discs, each with its own white icon, carry all the colour. The board beside the field puts the target in a white box and pops a small ring whenever someone scores. Scoring earns XP, the points plus ten for a win; levels unlock 14 colours beyond the first ten, and the stats stay on the device. On a phone held sideways, holding the left or right half of the screen steers. The page is in German and English and installs to a home screen.
Eine Linie, die nie anhält
CurveExtreme ist unser eigenes Kurvenspiel für das Nachmittags-Meeting, in der Tradition von Achtung, die Kurve!. Alle lenken eine Linie, die nie anhält, nach links oder rechts und sonst nichts. Ab und zu lässt sie eine kurze Lücke, und wer eine Linie oder die Wand berührt, ist für die Runde raus, auch an der eigenen Linie. Crasht eine Kurve, bekommen alle, die noch fahren, einen Punkt, und wer zuerst zehn Punkte pro Gegner hat, mit zwei Punkten Vorsprung, gewinnt das Spiel. Teams spielen stattdessen um Rundensiege.
Wer ein Spiel startet, bekommt einen Raum für bis zu zehn Kurven mit einem Code aus vier Buchstaben, einem Link und einem QR-Code. Es gibt keine Konten: Ein Name, ein Siegel und eine Farbe reichen, und nach einem Neuladen ist man wieder in der Runde. Bis zu vier Leute können sich auch einen Rechner teilen, mit je zwei Tasten, in einem Modus, der ganz in der Seite läuft.
Die Steuerung, gemessen
Im Meeting haben wir vorher CurveCrash gespielt, also musste dieses Spiel dessen Steuerung treffen. CurveExtreme ist ein eigenes, getrenntes Spiel: Seine Zahlen wurden an den Replays gemessen, die CurveCrash öffentlich zeigt, Bild für Bild, indem der Kopf jeder Linie verfolgt und ihre Bögen und Lücken ausgemessen wurden. Eine Linie fährt 90 Einheiten pro Sekunde, eine gehaltene Taste lenkt sie auf einen Kreis mit 35 Einheiten Radius, 147 Grad pro Sekunde, und sie ist 6,9 Einheiten breit. Lücken sind 16 Einheiten lang und kommen zufällig, im Schnitt nach 158 Einheiten Linie. Eine Runde beginnt mit 2,5 Sekunden Stillstand, ein Pfeil zeigt jede Richtung, dann 2,5 Sekunden Fahrt ohne Linie, und eine entschiedene Runde läuft noch 4,65 Sekunden weiter, bevor das Feld geleert wird.
Jede Zahl ist Daten
Keine dieser Zahlen steht im Spiel selbst. Sie liegen in einem Fahrprofil, neben den 25 Powerups und den Modi, von Basic und None bis GS++ mit doppeltem Tempo, und Custom, wo jedes Powerup einzeln an- oder ausgeht. Die Farbe eines Powerups sagt, wen es trifft: grüne dich, rote alle anderen, blaue das ganze Feld. Im Raum zeigt das Feintuning des Hosts jede Zahl des Fahrgefühls als Regler mit dem gemessenen Wert als Markierung, wendet eine Änderung ab der nächsten Runde an und speichert das Ergebnis auf Wunsch als Profil fürs nächste Spiel.
Eingaben statt Positionen
Das Netz funktioniert so, wie viele Echtzeitspiele es machen, am bekanntesten aus Kampfspielen: deterministischer Lockstep mit Rollback. Von CurveExtreme sind die Umsetzung und ihre Abstimmung. Keiner Seite wird je gesagt, wo eine Kurve ist. Eine Runde beginnt mit ihrem Startwert für den Zufall und der Serverzeit ihres ersten Frames, und jede Seite simuliert die ganze Runde selbst, nach der Uhr des Servers: Die Seite misst diese Uhr alle paar Sekunden mit einem Ping, und in welchem Frame sie ist, kommt immer von der Uhr, nie vom Mitzählen. Unterwegs sind nur Lenkwechsel, eine kleine Nachricht, wenn eine Taste runtergeht, und eine, wenn sie losgelassen wird, gestempelt mit dem Frame und dem Tausendstel des Frames, in dem es geschah. In einer Testrunde zu zweit hat eine Seite 14 Nachrichten bekommen und 8 geschickt.
Die eigene Kurve lenkt sofort, weil der Lenkwechsel in die Runde der eigenen Seite geht, bevor er losgeschickt wird. Der einer anderen Person kommt einen Moment später; ist sein Frame schon gezeichnet, geht die Seite zu einem Schnappschuss davor zurück und simuliert neu vorwärts, und das endet genau dort, wo es geendet hätte, wäre der Lenkwechsel von Anfang an da gewesen. Wer nur zuschaut, sieht das Spiel 200 Millisekunden später, damit nichts springt.
Der Server pfeift
Ein Node-Server ohne Abhängigkeiten simuliert dieselbe Runde 150 Millisekunden hinter der Uhr. Einen Lenkwechsel, dessen Frame er noch nicht erreicht hat, nimmt er an und gibt ihn an alle anderen weiter; einer, der später kommt, wird abgelehnt, und die Seite nimmt ihn zurück und schickt, was gerade gedrückt ist. Der Server entscheidet, wer raus ist, wenn zwei Bildschirme sich uneinig sind, und er führt die Punkte, die Runden, die Teams und die Farben. In einen Raum kommt man in zwei Schritten: Ein Platz wird per HTTP reserviert, und damit öffnet sich der WebSocket des Raums, über den kompakte Binärnachrichten laufen. Wer mitten in einer Runde dazukommt, bekommt ihren Start und jeden Lenkwechsel bis dahin und simuliert sie bis zur Gegenwart. Der Host kann außerdem jemanden aus dem Raum nehmen.
Dieselben Bits auf jedem Bildschirm
Damit jede Seite dasselbe Spiel zeichnet, muss jede Seite dieselben Zahlen rechnen, bis aufs letzte Bit. Sinus und Kosinus von JavaScript dürfen sich in diesem letzten Bit zwischen Chrome und Safari unterscheiden, und hier kann ein letztes Bit entscheiden, ob eine Linie durch eine Lücke schlüpft oder crasht. Deshalb rechnet das Spiel Sinus und Kosinus selbst, nur mit Addition, Subtraktion, Multiplikation und Division, vergleicht Abstände ohne Wurzeln und nimmt allen Zufall aus dem Startwert der Runde. Zur Probe wurden 24 Runden zu zehnt mit jedem Powerup in Node und in der Engine von Safari gespielt und verglichen: Sie endeten gleich. Die Tests spielen außerdem Runden mit Lenkwechseln, die einen Frame oder fast zwei Sekunden zu spät ankommen, und prüfen, dass jede Runde trotzdem im selben Zustand endet.
Klassisch schwarz
Das Feld ist schwarz in einer dünnen weißen Linie, und die Linien sind flach mit geraden Enden, so tragen die Kurven und die Powerup-Scheiben, jede mit ihrem eigenen weißen Zeichen, alle Farbe. Die Tafel neben dem Feld zeigt das Ziel in einem weißen Kasten und lässt einen kleinen Ring aufspringen, wenn jemand punktet. Punkte bringen XP, die Punkte plus zehn für einen Sieg; Stufen schalten 14 Farben über die ersten zehn hinaus frei, und die Statistik bleibt auf dem Gerät. Auf einem quer gehaltenen Handy lenkt man, indem man die linke oder rechte Bildschirmhälfte hält. Die Seite gibt es auf Deutsch und Englisch, und sie lässt sich auf den Home-Bildschirm legen.