← terug naar de arena
Making of

Hoe deze wedstrijd in elkaar zit

Wat je ziet is een voetbalwedstrijd zonder poespas. Tweeëntwintig spelers, een scheidsrechter, twee grensrechters, en verder niemand die zich ermee bemoeit. Beide ploegen worden door de computer bestuurd. Er valt niets te winnen en niets te doen. Dat is precies de bedoeling.

Alles wordt ter plekke getekend

In dit spel zit geen enkele afbeelding, geen enkel 3D-model en geen enkel geluidsbestand. Alles wat je ziet en hoort wordt bij het opstarten in de browser berekend.

Het veld

De maaistrepen, de middencirkel, de strafschopgebieden, de penaltybogen en de hoekbogen worden met gewone tekenopdrachten op een onzichtbaar canvas gezet van 2048 pixels breed, en dat canvas wordt vervolgens over het gras gespannen. De afmetingen zijn echt: 105 bij 68 meter, doel van 7,32 breed en 2,44 hoog.

Het gras is niet één kleur groen maar wordt punt voor punt berekend: elf maaibanen die om en om van je af en naar je toe liggen, met daaroverheen drie lagen ruis voor pollen en sprietjes. Waar veel gelopen wordt is het kaler — in de middencirkel, voor de doelen en langs de zijlijn. De belijning is twee keer getrokken, eerst een vage brede onderlaag van kalk die in het gras getrokken is en daarbovenop de verse lijn, waarna er nog een paar duizend gaatjes uit geknipt worden. Kalk is nooit egaal.

De bal, en waarom hij eerst flikkerde

De eerste bal had een lelijke, meedraaiende zwarte vlek. Dat was geen toeval maar een klassieke fout: er waren vijf vlekken op een plat vierkant getekend en dat vierkant was om een bol gespannen. Bij een bol lopen alle textuurpunten samen in de polen, dus een nette vlek op het vlak wordt op de pool een uitgesmeerde punt.

De nieuwe bal is andersom gemaakt. Voor elk beeldpunt wordt eerst uitgerekend wélke richting op de bol het voorstelt, en pas daarna of die richting binnen een zwart vlak valt. Het patroon staat dus op de bol en niet op het vlak: geen naad, geen pool, geen geflikker. En omdat je nu toch op de bol rekent, kun je net zo goed de echte vorm nemen — twaalf zwarte vijfhoeken op de punten van een icosaëder, met witte zeshoeken ertussen. Dat is precies een voetbal.

Het publiek

Tienduizend toeschouwers, elk met schouders in een eigen kleur en een hoofd erop, gezet in rijen die om en om een halve stoel opschuiven. Dat rijenpatroon is belangrijk: willekeurig strooien geeft altijd klonten en gaten, terwijl een raster met een kleine verschuiving er juist uitziet als echte tribunestoelen. Er lopen trappen doorheen, er zijn vakscheidingen, en hier en daar is een stoeltje leeg. In een latere versie worden het losse figuren die kunnen opstaan, juichen en wegduiken.

De spelers

Elk poppetje bestaat uit een stuk of twaalf bollen en cilinders in een toon-arcering met vijf grijstinten. De benen en armen hangen aan draaipunten, en hun uitslag hangt af van de snelheid: hoe harder iemand loopt, hoe wijder de pas. Er is geen animatiebestand, alleen een sinus.

De tenues zijn geweven texturen in plaats van vlakke kleur. Vulkaan speelt in banen, IJsbeer in een effen shirt met een borstband, en de kousen hebben een ring. Omdat het lijf een bol is, lopen verticale banen op de textuur vanzelf rondom het lichaam. Alle spelers van één ploeg delen dezelfde textuur — anders zou elk poppetje zijn eigen kopie in het geheugen krijgen.

De verslaggever spreekt geen Nederlands

Wat je hoort is geen opname en geen taal. Een zaagtandgolf gaat door twee banddoorlaatfilters die de klankkleur van een klinker nabootsen — a, o, e, oe, i, u. Daar worden lettergrepen van gemaakt.

Het trucje zit in de timing. Elke keer dat de bal van voet wisselt, komt er één lettergreep. Een reeks korte tikjes wordt daardoor een ratel; een speler die lang aan de bal blijft levert één uitgerekte klank op. En binnen een reeks kruipt de toonhoogte omhoog, tot het stil wordt en hij weer laag begint.

Dat is bewust zo gebouwd. Vroeger noemden radioverslaggevers in één ademloze stroom de namen van de spelers die aan de bal waren. Als je niet luisterde naar de woorden maar naar het ritme, hoorde je precies wat er op het veld gebeurde. Dat ritme is hier nagebouwd, zonder de woorden.

Wat je hoort zijn geen losse lettergrepen maar namen. Voetbalnamen hebben twee of drie lettergrepen met de klemtoon op een vaste plek — KOE-man, GUL-lit, van-PER-sie, ma-ra-DO-na — en dát patroon is wat je herkent, niet de letters. Dus krijgt één klank bijna de helft van de tijd en wordt luider uitgesproken, en zakt de laatste weg in toonhoogte zoals dat aan het eind van een naam gaat.

Het publiek is bruine ruis door een laagdoorlaatfilter, waarvan het niveau meebeweegt met hoe dicht de bal bij een doel is. Het fluitje is een driehoeksgolf met een trilling van achttien keer per seconde erop.

De trap op de bal was eerst een tikje: één sinus die in tachtig milliseconden omlaag zakte. Een echte trap tegen een opgepompte bal bestaat uit drie dingen tegelijk — de harde klap van de schoen, de korte holle resonantie van de bal zelf, en het ruisen van leer op leer. Alle drie zitten er nu in, en ze schalen mee met de kracht: een pass klinkt dof, een uithaal knalt.

Elke wedstrijd heeft een nummer

Bovenin staat een nummer. Dat is geen versiering: de hele wedstrijd wordt eruit afgeleid. Elke keuze die de computer maakt — welke pass, welk schot, of een tackle slaagt, zelfs de vlekken op de bal — komt uit één reeks die bij dat nummer begint.

Typ hetzelfde nummer op het beginscherm en je krijgt exact dezelfde negentig minuten. Dezelfde doelpunten, dezelfde gele kaarten, in dezelfde volgorde. Geef het nummer aan iemand anders en die ziet precies wat jij zag.

Daarvoor was één ding nodig dat je niet ziet: de simulatie rekent altijd in stapjes van precies een zestigste seconde, ongeacht hoe snel jouw computer is. Zonder die vaste stap zou hetzelfde nummer op een snellere machine een andere wedstrijd opleveren, en dan is het nummer waardeloos.

De valkuil van de tijdversnelling

Dat laatste verdient uitleg, want het is de meest gemaakte fout in simulaties en hij is verraderlijk: alles lijkt te werken tot je op de versnelknop drukt.

Vrijwel elke bewegingscode gebruikt door elkaar heen twee soorten formules. De eerste is de eerlijke:

positie = positie + snelheid × verstreken_tijd

Verdubbel je de verstreken tijd, dan gaat het voorwerp precies twee keer zo ver. Netjes. Maar overal waar iets soepel ergens naartoe moet bewegen — een camera die bijdraait, een speler die op snelheid komt, een waarde die langzaam ergens naartoe kruipt — staat de tweede soort:

waarde = meng(waarde, doel, verstreken_tijd × 6)

Die formule is niet eerlijk. De mengfactor kan namelijk nooit boven de één uitkomen: hij loopt vast. Bij een normale beeldsnelheid merk je daar niets van, want dan is die factor een tiende en gedragen beide formules zich hetzelfde. Maar vermenigvuldig de verstreken tijd met tien, en de eerste formule schaalt keurig mee terwijl de tweede tegen zijn plafond aanloopt en niet sneller wordt.

Het gevolg is een simulatie die bij versnelling stilletjes uit elkaar valt. Niet met een foutmelding, maar met een verschuiving: wie de eerlijke formule gebruikt schiet vooruit, wie de andere gebruikt blijft achter. In een wandelsimulator is dat de speler die opeens harder loopt dan de rest van het peloton, terwijl er aan niemands snelheid iets veranderd is.

Er is een verleiding om dit op te lossen door alle formules van het tweede type op te sporen en te herschrijven. Dat werkt, maar het is dweilen: elke keer dat er iets nieuws bijkomt kan het opnieuw misgaan, en je merkt het pas als iemand toevallig weer op tien keer zet.

De echte oplossing is de tijdstap nooit aan te raken. Wil je tien keer zo snel, dan reken je tien keer dezelfde kleine stap, en niet één stap die tien keer zo groot is:

voor i van 1 tot 10: doe_één_stap(1/60)

Nu kán er geen verschil ontstaan, want iedereen in de simulatie krijgt letterlijk dezelfde tien stapjes. Het kost meer rekenwerk, maar het is de enige vorm die klopt — en je krijgt er twee dingen gratis bij. Natuurkunde blijft stabiel, want een grote tijdstap laat botsingen door elkaar heen schieten. En de simulatie wordt herhaalbaar, want de uitkomst hangt niet meer af van hoe snel de computer toevallig is.

Eén ding hoort er niet in. Rook, confetti en vuurwerk veranderen niets aan de wedstrijd, en die tien keer per beeld doorrekenen kost zoveel dat de beeldsnelheid instort — waarna het spel juist langzamer gaat in plaats van sneller. Wat het verloop bepaalt, hoort in de stap. Wat alleen mooi is, hoort bij het tekenen.

Ze spelen expres rustig

De AI is niet gebouwd om te winnen. Een speler met de bal weegt af hoeveel druk hij voelt, hoe ver het doel is en welke medespeler ruimte heeft, en kiest dan meestal de veilige optie. Af en toe gaat er een lange bal in de ruimte, want zonder dat blijft het te veel in het middenveld hangen.

Het resultaat is een wedstrijd met een paar doelpunten en veel niks. Dat is geen gebrek. Een wedstrijd waarin voortdurend iets gebeurt is binnen tien minuten vermoeiend; een wedstrijd waarin bijna nooit iets gebeurt kun je uren aan laten staan.

Wat er onder de motorkap al klaarligt

Sommige dingen zijn gebouwd voor wat nog komt.

WatWaarvoor
Vaste tijdstapHerhaalbare wedstrijden, en straks stabiele natuurkunde
HerhalingsgeheugenTwintig seconden, van alles wat zich aanmeldt
Vier catacombe-mondenOpkomst nu; straks komt er ander volk doorheen
Losse chaos-moduleWordt in deze versie eenvoudigweg niet geladen

Het herhalingsgeheugen is opzettelijk dom gehouden. Het weet niet wat een speler is of wat een bal is; het kent alleen objecten die zich hebben aangemeld met de mededeling hoeveel getallen ze nodig hebben. Daardoor kan er later van alles bij zonder dat er iets aan verandert.

Waarmee het gemaakt is

← terug naar de arena