Gå til hovedindhold
Hjem
GrN.dk

Main navigation

  • Artikler
  • Cases
  • Ydelser
  • Din digitale projektleder
  • Om Greg Nowak
  • Billedgalleri
  • Kontakt
User account menu
  • Log ind

Bliv en del af mit community / gratis nyhedsbrev — tilmeld dig her

Brødkrumme

  1. Hjem
  2. Cases

Et mobilspil fra 2020, genopbygget til browseren — med global highscoreliste

Client
GrN.dk — internt projekt
Sector
Browser- og mobilspil
Periode
Bygget 2020 · genopbygget og relanceret juli 2026

At a glance

veganpower.grn.dk er Vegan Power, et fang-frugten-arkadespil med en regel, man forstår på ét sekund: spis frugt, ikke venner. Frugt falder, og du fanger den. En kylling, en ko eller en pingvin falder, og du undviger den — hver gang du rammer én, koster det et af dine syv hjerter. Det begyndte i 2020 som et lille Flutter- og Flame-spil til Android, udgivet på Google Play samme december. I 2026 blev det skilt ad og genopbygget: det åbner nu i enhver browser uden installation og uden konto, fører en global highscore-tabel på sit eget lille API og har en multiplayer-beta, hvor to til fire spillere deler én arena og skubber hinanden væk fra frugten.

89 commits fra 2020 til 2026 — samme spil i to epoker
34 spiltests + 29 API-tests gater hvert eneste push
20 Hz server-autoritativt relæ · 2-4 spillere · runder på 90 sekunder

The challenge

Udgangspunktet var et fem år gammelt hobbyspil, der kun fandtes som app. For at spille det skulle man finde det i en app-butik og installere det — en høj barriere for noget, der tager halvandet minut at nyde. Indeni bar koden også præg af sin alder: én lang game-loop, der tegnede hvert element i hånden, en highscore gemt kun på enheden, og ingen mulighed for at teste spillereglerne uden at køre hele appen.

Briefet for genopbygningen var derfor ikke "tilføj features". Det var: gør spillet spilbart med det samme fra et link, på telefon eller desktop, hvor som helst i verden; giv scoren et sted at bo, så en runde betyder noget; og gør det sådan, at det forbliver billigt i drift og kan vedligeholdes ét kort ad gangen i stedet for i lange, risikable arbejdssessioner.

To begrænsninger gjorde det sværere, end det lyder. For det første skal et Flutter-spil i browseren hente en stor grafik-runtime, før det kan tegne en eneste frame — og serveren står i Europa, mens en god del af spillerne er i Asien, så "det virker her" siger intet om, hvordan det føles der. For det andet er den feature, folk oftest beder om — realtids-multiplayer — et fysikproblem, ikke et feature-ønske: i et reaktionsspil mærkes afstanden mellem spillerens finger og serveren direkte, og ingen mængde kode gør lysets hastighed kortere.

The solution

Spillet. Fem slags frugt falder (banan, appelsin, pære, jordbær, vandmelon) og seks dyr (kylling, ko, hund, elefant, pingvin, gris). Frugt giver point, og fire fangster i træk uden at ramme et dyr starter en multiplikator, der kravler op til fem gange; rammer man et dyr, nulstilles den, og det koster et hjerte — man har syv. Faldhastigheden og din egen fart stiger begge med scoren, så en runde starter blidt og slutter hektisk. Hver fangst afspiller et af tretten små stemmeklip — "yum"- og "no!"-lydene findes på en håndfuld sprog, heriblandt dansk, polsk, tysk og thai — over ét jazzet loop, med screen shake og en partikelbyge ved sammenstød.

En moderne motor under det samme spil. Den håndrullede render-loop er væk. Spillet er nu et almindeligt Flame-spil, hvor skærmbillederne er router-sider, og hjerter, score, combo, knapper og leaderboard-panel er selvplacerende komponenter. Mindst lige så vigtigt: reglerne, der før var filtret ind i loopet, er nu rene funktioner uden grafik på — sværhedskurven, banegeometrien og kollisionstjekket, der afgør, om du fangede noget. Sidstnævnte er en swept-test frem for et øjebliksbillede, så en hurtigt faldende frugt ikke kan teleportere lige igennem spilleren mellem to frames. 34 automatiserede tests dækker de regler, plus et golden image af startskærmen.

At få det til at opføre sig ordentligt i en browser. To ting blev lært på den hårde måde og står nu som advarsler i koden. Spillet renderer kun pålideligt som en ren game-widget — hvert forsøg på at pakke det ind i en layout-widget gav sort skærm — så letterboxing sker i stedet inde i spillet: én centreret spillekolonne på ni felter, som baggrunden, HUD'en, knapperne og hvert spawn-punkt forankres til, uanset vinduesstørrelse. Og grafik-runtimen blev serveret uden caching, hvilket betød cirka 28 KB/s til en fjern spiller: en caching-regel på edgen bragte det op på omkring 60 MB/s verden over — forskellen på "sort skærm, det må være i stykker" og "det åbner bare".

Et lille API helt for sig selv. Globale scores kører på en FastAPI-service med en SQLite-fil bagved, på samme server, proxyet på vpg-api.grn.dk. Der er ingen konti og ingen e-mailadresser: identiteten er et anonymt id, der udstedes i browseren ved første spil, med et valgfrit kaldenavn, der går gennem et bandeordsfilter, og en overførselskode, hvis du vil tage din profil med til en anden enhed. Fordi et offentligt score-endpoint er en invitation, er indsendelser signerede, tidsstemplede, rate-limitede pr. enhed og pr. adresse og har et loft, ingen ærlig runde kan nå. (Én detalje værd at huske: det gratis certifikat på edgen dækker kun ét subdomæneniveau, så api.veganpower.grn.dk kunne aldrig virke, og API'et bor i stedet på vpg-api.grn.dk.)

Fruit Rumble — multiplayer-betaen. To til fire spillere joiner via en rumkode på fire bogstaver til en runde på 90 sekunder i en fælles arena, hvor et sammenstød skubber modstanderen — stjæl den frugt, de sigtede efter, eller skub dem ind i en ko. Serveren ejer simulationen og kører den tyve gange i sekundet, for ellers bliver to spillere aldrig enige om, hvem der skubbede hvem; klienterne sender kun deres input. Din egen figur forudsiges lokalt og afstemmes mod serverens kvittering, resten af verden interpoleres gennem en buffer, der dimensionerer sig selv efter den jitter, den faktisk måler, og en NET-visning på skærmen viser rundturstid, jitter og aktuel buffer, så oplevelsen kan diskuteres med tal i stedet for tillægsord.

Udgivelse — ved hvert push. En build kører inden for ti minutter efter et commit og nægter at gå ud, hvis noget er rødt: analyzeren, de 34 spiltests og de 29 API-tests gater den alle. En grøn build deployer webversionen, purger edge-cachen, bygger en signeret Android-release, installerer den på en rigtig Android-emulator og kører en launch-smoketest — og kun en bestået smoketest promoverer det offentlige downloadlink, spejler filen til Drive og uploader til butikkens interne testspor. Et versionstag er det, der promoverer en build til produktion. I begge tilfælde ankommer en mail med "ready" eller "BLOCKED" — med begrundelsen.

Se det, ikke antage det. Et spil, der renderer på et canvas, viser intet til et script, der læser siden, så verifikation sker med rigtige øjne: en GPU-browser og en rigtig Android-emulator, der styres, screenshottes og tjekkes. Billedet øverst på siden blev lavet på den måde — en agent åbnede det live site, ventede på første frame, trykkede START med rigtige touch-events, spillede en runde og fangede den.

The results

Vegan Power er live på veganpower.grn.dk: åbn linket og spil, på telefon eller desktop, uden installation, uden konto og uden at der gemmes andet om dig end et anonymt id i din egen browser. Android-versionen findes stadig for dem, der vil have den — en signeret APK fra seneste commit plus den oprindelige 2020-udgivelse på Google Play.

Den globale highscore virker hele vejen igennem: afslut en runde, og game-over-skærmen viser den globale top tre og din egen placering, leveret af projektets eget API. Det blev bekræftet i den samme automatiserede session, der producerede screenshotet ovenfor.

Driftsomkostningerne er bevidst tæt på nul: statiske filer bag et CDN, én lille API-proces og en SQLite-fil, som den natlige backup allerede dækker.

Hvad der ikke er færdigt — med ejerens egne ord. Multiplayer er mærket beta på startskærmen, fordi det er, hvad det er. At flytte relæet til en forbindelse, der lander på en nærliggende edge-lokation, skar netværkets rundtur fra cirka 250 ms til omkring 100 ms for spillere i Thailand, og relæets eget arbejde tager under et millisekund — men alt andet end din egen figur tegnes gennem en udjævningsbuffer, så modstandere og frugt ankommer stadig et kvart sekund efter din finger. Dommen efter en rigtig runde var "bedre, men stadig ikke spilbart", og det ærlige svar er, at det at lukke hullet kræver, at hele verden forudsiges lokalt, og at fangster bedømmes mod det, spilleren faktisk så. De to dele er designet og afgrænset; de er ikke bygget. Solospillet, som er det spil, de fleste åbner, er upåvirket.

Opdatering, august 2026. Spillet tester nu sig selv på to niveauer: en white-box-suite kører den rigtige Flame-engine headless (menu-flow, golden-image-renderingstjek, lydløse lyd-doubler injiceret til CI), og en black-box-smoketest driver den faktiske Android-build gennem Appium og Robot Framework på en rigtig device-lab-maskine — trykker, hvor en spiller ville trykke, og verificerer, hvad en spiller ville se. Begge er koblet på CI, så en regression fælder pushet, ikke spilleren.

Det andet, projektet demonstrerer, er, hvordan det blev lavet: hele genopbygningen kom af et Trello-board ét kort ad gangen, hvert samlet op af en AI-agent — web-builden, caching-fixet, leaderboardet, moderniseringen af motoren, multiplayer-relæet og latency-målingerne kan hver især spores til det kort, der bad om dem, inklusive dem, hvor brugeren blot skrev "web build is not doing well on full screen" og fik en rodårsag tilbage. Der er en letlæst gennemgang af selve spillet her: Vegan Power: det lille spil om at spise frugt, ikke venner.

Spis frugt, ikke venner.

Hele design-briefet — første linje i spillets README fra 2020

Got a project that needs the same kind of hands-on delivery?

Your digital project manager

Anmeld Greg på Google

Greg Nowak Google-anmeldelser

 

Skriftlige anbefalinger fra Trafik og Veje, Aarhus Kommune (2011) og AgroTech (2010) — læs dem på LinkedIn.

Illustrated infographic summarizing: OpenAI File Search: Interne dokumenter kræver governance, før du kan stole på dem
OpenAI File Search: Interne dokumenter kræver governance, før du kan stole på dem
2026-08-18

OpenAI File Search gør retrieval let at demonstrere, men produktion kræver opryddede dokumenter, metadata, en gennemtænkt vector store-struktur, regler for udløb og omkostningsstyring.

Illustrated infographic summarizing: Fra leverandørfaktura til bogføring: AI med en kontrolpost
Fra leverandørfaktura til bogføring: AI med en kontrolpost
2026-08-18

AI kan lette arbejdet med leverandørfakturaer, men sikker bogføring kræver validering, dubletkontrol, godkendelse og et tydeligt kontrolspor.

Flere artikler
RSS feed

Footer

  • Alle artikler
  • Kontakt

GrN.dk — AI-automatisering, webplatforme, weboptimering, datahåndtering og logistik.

© 2026 GrN.dk · LinkedIn · Kontakt · AI-automatisering på dansk: nowa.dk

Bag GrN.dk: Individual Entrepreneur Codecrafter · Tax ID 305669096 · Bakhtrioni St. 22, 0194 Tbilisi, Georgien · officielt virksomhedsregister