Gioca a UNI!

Diari di sviluppo

Ricostruire il gioco in 3D

Fino alla 0.6 il tavolo di UNI era HTML. Ora e’ una scena 3D accelerata dall’hardware. Qui spiego come e perche’ ho affrontato la fatica di farlo.

Com’era il tavolo

Per tutta la 0.5 il tabellone era semplice HTML e CSS, reso con fatica LEGGERMENTELEGGERMENTE responsive (non lo era). Inclinavo tutto con una prospettiva CSS per simulare un tavolo, e trascinare una carta si basava su una libreria di drag-and-drop. Tutto era statico e le animazioni erano scritte a mano nel codice.

Funzionava. Era un inferno di un tipo speciale, ma funzionava. Aveva pero’ anche un tetto, bidimensionale. Le carte non potevano disegnare un arco sul tavolo, girarsi a mezz’aria o infilarsi dietro un’altra carta. E un layout pensato per quattro posti, in un PARTY GAMEPARTY GAME, e’ molto limitante.

0.60.5.50.5.50.6

Perche’ ho cambiato

UNI esiste per diventare un gioco di carte personalizzabile, e la schermata di gioco ne e’ il cuore. Una schermata bloccata a quattro posti, senza spazio per muoversi, senza 3D, senza animazioni guidate dai dati e senza shader era un vero limite. Il tavolo funzionava inoltre solo in orizzontale, quindi i telefoni, la base di utenti principale, non potevano davvero giocare (e io non potevo registrare contenuti per Instagram o altri video brevi). Regole, carte e aspetti personalizzati devono tutti comparire su quella schermata, e un layout cosi’ scadente non avrebbe mai potuto mostrarli.

Quindi la schermata doveva smettere di essere quello che era e diventare una base su cui costruire.

Cos’e’ Threlte

Three.js e’ la libreria standard per mettere il 3D in un browser. Threlte e’ un insieme di componenti Svelte costruiti attorno a essa. Invece di costruire una scena chiamando funzioni in ordine, la descrivi come il resto di un’app Svelte: una carta e’ un componente, un posto e’ un componente, la camera e’ un componente. Proprieta’ e stato arrivano come al solito.

Per questo l’ho scelta. Il tavolo 3D e’ ancora parte della stessa app, nient’altro doveva cambiare, e il lavoro necessario si e’ ridotto di molto.

Il mezzo passo

Siamo passati a Threlte, e ora? Tutto funzionava correttamente, ma le animazioni, ovviamente, no. Il volo delle carte continuava a passare da un overlay 2D di elementi della pagina, ormai rotto, steso sopra la tela 3D.

Visto il lavoro, anche quel codice andava eliminato: non avrei fatto tutto questo per un ambiente 3D per poi rinunciare al contenuto principale del gioco, cioe’ carte succose e ben animate. Cosi’ ho sostituito l’intera cosa. Ora le destinazioni del volo sono coordinate nello spazio del mondo, prese dalle stesse funzioni pure che dispongono mani e posti. Se cambio la posizione di un giocatore, o quella del mazzo degli scarti, le carte si animeranno comunque correttamente, niente piu’ dolore!

Una coda, e ogni passo si puo’ saltare

Le animazioni girano come una coda seriale: un passo alla volta, in ordine, cosi’ una partita non diventa mai quaranta carte che volano insieme. La parte a cui tengo di piu’ e’ che ogni passo e’ saltabile. Clicca o tocca e il passo corrente salta al suo stato finale, poi la coda va avanti. Odio aspettare le animazioni nei giochi, quindi non avevo intenzione di costruire proprio quello che odio. Le partite veloci restano veloci!

Un passo e’ piccolo e stupido di proposito: muovere una carta, girarla, far tremare il mazzo, lampeggiare lo schermo. L’effetto di una carta e’ solo una catena di questi passi. Ed e’ anche la forma che useranno le carte delle mod, cosi’ nessuno deve scrivere codice di animazione per far sembrare una carta qualcosa.

C’era un ultimo problema. Il client doveva indovinare quei passi confrontando uno stato di gioco con il successivo e, come puoi immaginare, sbagliava spesso. Nella 0.6 e’ il server a mandare la sequenza di eventi e il tavolo si limita a riprodurla. Le carte volano dove sono andate davvero!

A che punto siamo nella 0.6

Il nuovo tavolo 3D in una partita da 16 giocatori
Una partita Corsa da 16 giocatori sul tavolo 3D.
Un inverti e un cambio colore sul tappeto
Un inverti blu cade su un inverti blu, poi un inverti giallo gira il cerchio e colora il tappeto di giallo.
  • La camera guarda dritto verso il basso e la scena si adatta a qualsiasi forma di schermo, da un telefono in verticale a un monitor largo. I telefoni erano il punto di tutto, dopotutto.
  • I posti sono disposti su un arco attorno al tavolo, cosi’ sedicisedici giocatori ci stanno.
  • Ogni carta e’ una singola mesh che campiona un unico atlante di texture condiviso, invece di una pila di strati in lotta tra loro.
  • Una partita si apre con una cinematica di distribuzione. Saltabile, ovviamente.
  • Le carte speciali atterrano con un breve hit-stop, un piccolo colpo di camera e un lampo del colore della carta. Salta la coda e l’impatto sparisce e la camera torna al suo posto.
  • Un cambio colore manda un’onda sfumata a pixel sul tappeto, a 12 fotogrammi al secondo per restare in tema con la pixel art, e le frecce attorno al tappeto si girano quando il gioco inverte.
  • Il movimento ridotto e le impostazioni di animazione abbassano tutto, per chi preferisce cosi’.

Cosa viene dopo

Gli shader per singola carta e gli effetti a schermo intero entrano entrambi nella stessa coda, e sono i prossimi. Sono quelli che permetteranno a una carta modificata di sembrare qualcosa di piu’ di un numero ricolorato.

L’elenco completo di cosa e’ cambiato nella 0.6 e’ nel changelog.

← Diari di sviluppo