Hoe data oriented design de framerate van snelle games stabiel houdt

arrow-down

Cuphead tikt strak 60 beeldjes per seconde aan en zakt daar bijna nooit onder, ook niet als het scherm ontploft van projectielen, parries en de animatiefases van een eindbaas. Dat gebeurt niet “gewoon”. Onder die ogenschijnlijk simpele 2D-look zit een bewuste keuze in de enginearchitectuur: data oriented design, oftewel DOD.

Als speler neem je het snel voor lief dat The Devil of King Dice soepel blijft lopen tijdens hun drukste patronen. Achter de schermen komt die stabiliteit uit heel concrete keuzes over waar data in het geheugen landt, hoe de CPU die data binnenharkt en hoe code is ingericht rond cachelijnen in plaats van rond losse objectjes.

Cuphead featured thumbnail over data oriented design en stabiele framerate in snelle actie

Waarom objectgeoriënteerd denken vastloopt bij actiepieken

Veel games starten vanuit objecten: elk projectiel een instantie, elke vijand een klasse met methoden en verwijzingen naar andere systemen. Dat is overzichtelijk en het sluit aan bij hoe designers over een game praten. Alleen krijg je het zwaar als er per frame ineens honderden actieve entiteiten bijkomen.

Het probleem zit vooral in geheugentoegang. Objecten belanden vaak verspreid op de heap, met pointers die alle kanten op wijzen. Op het moment dat de CPU steeds nieuwe locaties moet lezen, groeit de kans op een cache miss, en zo’n miss kost zo tientallen tot honderden klokcycli binnen je frame van 16,6 milliseconden.

In een bullet hell-achtig gevecht, zoals tegen Dr. Kahl’s Robot, slurpt de engine per frame enorme hoeveelheden posities, snelheden en hitboxes naar binnen. Staat die data netjes achter elkaar, dan leest de processor hele brokken in één keer. Ligt alles verspreid, dan krijg je precies die microhapering die gevorderde spelers meteen merken tijdens een krappe dodge.

Wat data oriented design anders doet

Data oriented design zet de volgorde om: je begint bij de data en pas daarna komt de vorm van je code. Eerst kijk je welke bewerkingen het vaakst gebeuren en welke gegevens daarbij steeds samen gebruikt worden. Daarna organiseer je die gegevens zo dicht mogelijk bij elkaar in het geheugen, zodat de CPU minder hoeft te zoeken.

Een bekende uitwerking is de structure of arrays. In plaats van één lijst met projectielobjecten, waar elk object z’n eigen positie, snelheid en type meedraagt, werk je met meerdere compacte arrays. Denk aan één array voor alle x-posities, één voor alle y-posities en één voor alle snelheden, zodat het updaten van alle projectielen per frame een strakke, aaneengesloten geheugenrun wordt.

Het verschil in de praktijk

De winst komt zelden uit één magische tweak, maar uit het wegpoetsen van veel kleine stotters die zich anders opstapelen. Op moderne CPU’s is geheugentoegang vaak de echte bottleneck en niet pure rekenkracht. Met een slimme dataroute blijft de pipeline gevuld, terwijl een rommelig patroon cores laat wachten.

  • Minder cache misses doordat data die samen gebruikt wordt ook echt naast elkaar staat in het geheugen.
  • Betere benutting van SIMD-instructies, zodat de CPU meerdere waarden tegelijk kan verwerken.
  • Voorspelbare framekosten, omdat de kosten per entiteit vrijwel lineair blijven opschalen.
  • Eenvoudigere parallellisatie, want data zonder onderlinge verwijzingen verdeel je makkelijker over meerdere threads.

Daarom blijft Cuphead ook op bescheiden hardware opvallend stabiel, terwijl de Delicious Last Course-bazen met gelaagde patronen voluit gaan. Het gevolg is dat je framebudget niet verdwijnt in onzichtbaar geheugengeschuifel.

Hoe past dit bij Cuphead’s technische DNA?

Studio MDHR bouwde Cuphead in Unity, net als veel andere videogames, en deed veel maatwerk voor animatie en gevechtslogica. Rendering was niet de grootste kluif, want de handgetekende frames spelen vooral af als sprite sequences. De druk zit eerder in het tegelijk bijhouden van patroontimers, projectielbanen, parry-vensters en collision checks.

Voor dat soort systemen werkt een datagedreven aanpak extra goed. Een parry-check hoeft bijvoorbeeld niet te snappen wie de speler “is” of welke animatie een pink object afspeelt. Belangrijk is alleen of twee hitboxes op het juiste frame overlappen, en door die controle los te trekken van een brede objectstructuur blijft de per-frame workload klein en voorspelbaar.

Van filosofie naar meetbare resultaten

Bij snelle actiegames draait het minder om je gemiddelde framerate en meer om 1 procent lows en frame pacing. Een game die gemiddeld 60 fps haalt maar elke twee seconden inzakt naar 40 voelt slechter aan dan een game die constant op 55 fps blijft. DOD pakt juist die uitschieters aan door piekkosten te verlagen.

Daarom investeren studio’s die twitch-gevoelige games maken, van fighters tot bullet hells, steeds vaker in datagedreven subsystemen voor fysica, AI en effecten. Grafische pracht trekt de aandacht, maar de speelbaarheid wordt beslist in milliseconden die je niet op een screenshot terugziet.

De bredere trend in de industrie

Dat DOD breder doorbreekt zie je aan de populariteit van entity component systems, met voorbeelden als Unity DOTS en Bevy. Grote studio’s bouwden dit soort oplossingen al langer intern, en inmiddels landen dezelfde principes ook bij middelgrote teams en indies. De reden is simpel: rommelige code wordt niet meer automatisch “weggewerkt” door snellere hardware.

CPU-klokfrequenties stijgen al jaren nauwelijks. Extra winst komt vooral uit meer cores, bredere SIMD-eenheden en snellere caches, en software moet daarop ingericht zijn om er echt van te profiteren. Voor Cuphead bepaalt dat of het soepel speelt op een Steam Deck, of dat je tijdens een run tegen een onverwachte stotter aanloopt.

Wat betekent dit voor hoe je games beoordeelt?

Als speler merk je DOD niet direct op. Er is geen achievement voor nette cache-benutting, en reviewers tikken zelden “structure of arrays” in hun conclusie. Wat je wél ervaart is het uitblijven van irritatie: geen stotter net voor een parry, geen inputlag die bij drukke patronen oploopt en geen onverklaarbare dip in de climax van een gevecht.

De interessantste les is dat sterke technische keuzes vaak onzichtbaar blijven. Ze vragen geen applaus, maar ze houden wel het ritme van een game intact, zeker in titels waar timing alles is. Cuphead laat zien dat een game met een jaren dertig uitstraling prima kan draaien op architectuurprincipes die in 2025 nog steeds tellen.

Wat je als speler meeneemt

Voelt een snelle actiegame tijdens de drukste momenten opvallend stabiel, dan zitten er meestal datagedreven keuzes onder de motorkap. Dat is geen marketingwoord, maar een heel concrete manier om hardware slimmer te gebruiken. De kern is goed samen te vatten.

  • Plaats data die samen wordt gebruikt ook samen in het geheugen.
  • Scheid logica van objectidentiteit waar dat kan.
  • Meet frame pacing, niet alleen gemiddelde fps.
  • Ontwerp systemen vanuit de drukste scène, niet vanuit het rustigste moment.

Studio MDHR bewijst met Cuphead dat deze aanpak net zo relevant is voor een handgetekende 2D-platformer als voor een AAA-shooter. De stijl aan de buitenkant verschilt, maar CPU-caches en frametijd blijven dezelfde harde realiteit. Als je eenmaal snapt waarom sommige games onder druk soepel blijven, kijk je met extra respect naar dat stille vakmanschap erachter.

Bas_SBW
Video Games Editor