~/projekty / blind-clue
BlindClue
Wieloosobowa gra dedukcyjna w czasie rzeczywistym: wszyscy dostają tajne słowo poza jednym graczem, który ma tylko podpowiedź i musi się wtopić.
- rola
- full stack: backend realtime, frontend w Vue
- czas
- maj – sie 2026
- typ
- własny
- stack
- TypeScript · Vue 3 · Pinia · Fastify · Socket.io · SQLite
01 / problem
Gra imprezowa wymaga, by wszyscy byli w tym samym momencie
Gra działa tylko wtedy, gdy wszyscy gracze przechodzą przez te same fazy razem: opis słowa, głosowanie, ujawnienie. Każda faza musi dotrzeć do każdego gracza na bieżąco, a punktacja musi być rozstrzygana w jednym miejscu.
02 / rozwiązanie
Gra sterowana przez serwer na Socket.io
Od dwóch do czterech graczy dołącza do lobby i gra trzy rundy opisywania słowa bez jego wymieniania, po czym głosuje, kto jest impostorem. Głosy są ujawniane, a przyłapany impostor może jeszcze zdobyć punkty, zgadując słowo. Serwer jest właścicielem stanu gry i punktacji; klienci wysyłają zdarzenia, takie jak joinGame, submitDescription i voteImpostor, a reagują na GameStarted, VotingStarted, VotesRevealed i GameEnded.
- [screenshot 1]
[podpis]
- [screenshot 2]
[podpis]
03 / architektura
Jak to działa
Monorepo pnpm: backend Fastify + Socket.io + SQLite zbudowany w warstwach Clean Architecture (encje domeny, przypadki użycia, serwisy aplikacji, adaptery) oraz frontend Vue 3 + Vite + Pinia + Tailwind. Trwające gry żyją w pamięci w GameManagerze i znikają po zakończeniu; kategorie i słowa zarządzane są endpointami administracyjnymi. Backend jest dostarczany jako obraz Dockera.
04 / wyniki
Efekt
05 / wnioski
Czego się nauczyłem
- Trzymanie trwających gier wyłącznie w pamięci upraszcza model; druga strona to fakt, że restart zakończyłby gry w toku.
- Zwracanie Result z każdej operacji czyni ścieżki błędów jawnymi i łatwymi do testowania, także dla punktacji przy przyłapanym i nieprzyłapanym impostorze.
galeria
- [zdjęcie]
[podpis]
- [zdjęcie]
[podpis]
- [zdjęcie]
[podpis]