← Toate articolele

Cum am construit Table Online — un joc de table multiplayer în Flutter pentru web, iOS și Android

Lecții tehnice din construirea unui joc real-time în Flutter, cu același cod care rulează în browser și nativ pe mobil. State management, sincronizare server, performanță 60fps.

Acum câteva luni am lansat Table Online — un joc clasic de table multiplayer pe care îl poți juca direct în browser pe table-online.ro, sau ca aplicație nativă pe iPhone și Android. Tot e construit în Flutter, cu un singur cod sursă pentru toate trei platformele. Acest articol e o privire în culisele inginerești.

De ce Flutter pentru un joc multiplayer

Decizia n-a fost evidentă. Pentru jocuri, mulți recomandă reflex Unity sau un engine custom. Am ales Flutter pentru trei motive concrete:

  1. Animațiile sunt clase de prim rang în Flutter. AnimationController, AnimatedBuilder, Hero, TweenAnimationBuilder — toate datele de mișcare ale pieselor de table și ale zarurilor sunt deja rezolvate de framework. N-a trebuit să scriem un physics engine.
  2. Web-ul ne-a permis adopția fără descărcare. Cea mai mare frecare în adopția unui joc mobil e instalarea. Cu Flutter web, utilizatorul intră, dă două click-uri, joacă o partidă. Ulterior, dacă îi place, instalează app-ul.
  3. Un singur codebase, trei platforme — și asta nu e doar un argument de marketing. Logica de joc, validarea mișcărilor, comunicarea cu server-ul — toate trăiesc în același fișier și se comportă identic peste tot.

Arhitectura

Pe scurt:

  • Frontend Flutter — UI, animații, input local. State management cu Riverpod.
  • Server Dart pe Cloud Run — autoritatea jocului. Fiecare mișcare e validată server-side; clientul doar propune.
  • WebSockets pentru sincronizare — o conexiune persistentă per partidă, mesaje tip protobuf pentru economisire de bandwidth.
  • Firestore pentru state persistent — profile utilizatori, istoric partide, leaderboard.

Decizia care a contat cel mai mult: serverul e source-of-truth. Clientul propune o mișcare, server-ul decide dacă e validă, apoi broadcast-ează rezultatul ambilor jucători. Asta elimină o clasă întreagă de cheating și face debugging-ul predictibil.

Performanță: cum am ținut 60fps în browser

Web-ul Flutter e mai complicat decât mobile-ul nativ pe partea de performanță. Câteva lucruri care au făcut diferența:

  • RepaintBoundary peste tablă — izolăm repainting-ul tablei de restul UI. Când mișcăm o piesă, nu repaintăm scor-ul.
  • HTML renderer pentru paginile cu mult text, CanvasKit pentru pagina de joc — Flutter web suportă două renderere și poți alege per build. Pentru pagina de joc, CanvasKit câștigă net.
  • Lazy loading al asset-urilor — texturile de piese, sunetele, animațiile de victorie se încarcă doar când sunt necesare.

Lecția cea mai utilă

Dacă aș începe din nou, aș începe cu varianta web înainte de mobile. E mai grea (Flutter web are mai puține tooluri și mai multe edge cases), dar te forțează să iei decizii arhitecturale corecte de la început — bundle size, lazy loading, optimizare imagini. Aceleași decizii fac mobile-ul mai bun ulterior.


Vrei să discutăm un proiect Flutter? Scrie-ne — răspundem în maximum o zi lucrătoare. Și dacă vrei să vezi rezultatul în acțiune, intră pe table-online.ro și joacă o partidă.