
Scrittura · 21 feb 2018
Aggiornare Snake '97
Le sfide di sviluppare un gioco popolarissimo
Qualche anno fa mio fratello ha rovesciato una birra sul mio iPhone in un bar di Amsterdam. Poverino, la birra olandese non gli è piaciuta quanto piace a me: è morto. In attesa del nuovo telefono ho usato un vecchio cellulare che sapeva fare solo tre cose: mandare SMS, telefonare e... Snake! Così è nata l'idea di Snake '97, e questo mese è arrivato il momento di aggiornare il gioco più amato di sempre.

Snake '97
Ho programmato il gioco Snake per la prima volta nel 2011, per iOS. Mi sono servite circa due settimane per avere un prototipo funzionante, con l'aspetto e la sensazione del vero classico degli anni '90. Per la grafica mi ha dato una mano l'altro mio fratello, facendo delle foto macro molto nitide del mio vecchio telefono (è ancora strano pensare che tanti di voi abbiano una copia del mio telefono in tasca).

È stato ripreso da alcuni blog importanti e così Snake '97 ha scalato le classifiche di tutto il mondo. Oggi si gioca ovunque, è tradotto in 53 lingue ed è disponibile per iOS, Android, Windows, ChromeOS e macOS.

Serviva un aggiornamento
Nel 2011 esisteva un solo iPhone, l'iPhone 4. Da sviluppatore potevi ignorare tranquillamente Android, e Windows Phone non era ancora stato nemmeno inventato. La vita era bella come può desiderarla uno sviluppatore (pigro): una sola dimensione di schermo.

Oggi Apple vende 8 iPhone e in giro ci sono milioni e milioni di dispositivi Android, tutti con schermi, processori, memoria e versioni del software diversi. Chiamarla una sfida è dire poco...
Per mantenere il divertimento di Snake '97 dovevo aggiornare il motore del gioco fin dalle fondamenta. In qualche modo dovevo far stare la grafica su ogni schermo del mondo e tenere conto delle differenze di potenza di calcolo e di memoria....

Un solo motore per domarli tutti
Le versioni originali del gioco avevano ognuna il proprio motore. Uno per iOS, uno per Android, uno per Windows e così via. Quando ho lanciato Snake 2k (la variante Snake II), ho semplicemente aggiunto altri motori. In tutto ho programmato 6 motori Snake diversi in Objective-C (iOS), Java (Android) e C# (Windows). Farli girare su dispositivi nuovi, con schermi, processori e memorie diversi, diventava sempre più difficile.
Ma questo mese ho preso il toro per le corna, in grande stile. Ho riprogettato e costruito un altro motore Snake. Ma questo doveva sostituire tutti i precedenti. Doveva girare su iOS, Android e Windows. Volevo un motore pronto per il futuro, per qualsiasi schermo e qualsiasi tipo di input (tastiera, touch, pencil, gamepad, joystick, quello che vuoi).

HTML5 spacca
Il web ha raggiunto la tecnologia delle app native. Sono arrivate tante nuove API che permettono esperienze interattive ricche su moltissimi dispositivi. Mi sono chiesto quanto sarebbe stato difficile far funzionare Snake '97 con la tecnologia web. C'era un solo modo per scoprirlo, e ho cominciato.
Grafica adattiva
Per prima cosa ho costruito il motore grafico basato sul canvas di HTML5 e su un sistema di ridimensionamento adattivo che avevo progettato per la versione Android di Snake '97. In sostanza il motore misura le dimensioni disponibili dello schermo, l'orientamento e la densità di pixel. Poi adatta automaticamente il materiale fotografico ad alta risoluzione al tuo schermo.

Il nuovo motore grafico tiene conto perfino di stranezze come il notch dell'iPhone X. Succede tutto in una frazione di secondo. L'ho progettato per reagire anche ai cambiamenti delle dimensioni dello schermo. Ora puoi giocare in verticale o in orizzontale, in una finestra o a schermo intero (o in split screen se hai un iPad).


Differenze di potenza di calcolo
Pensi che un gioco semplice non debba preoccuparsi della potenza di calcolo? Sbagliato! In un gioco come Snake il tempismo è essenziale. La gente gioca con la "memoria muscolare", e ripete i suoi tap sul touch screen senza pensare ai singoli movimenti.
Il motore del gioco deve essere prevedibile, deve girare in modo costante. Ma soprattutto l'esperienza deve essere la stessa, che tu abbia un vecchio dispositivo Android o un mostro a 6 core come l'iPhone X.

Ho usato la videocamera ad alta velocità dell'iPad Pro per filmare il gioco al rallentatore. Con il video ho potuto individuare le differenze di velocità, fotogramma per fotogramma. Ne è nato un sistema interno di benchmark (con timer che contano i millisecondi) che regola automaticamente la velocità del gioco, tarata con precisione sul tuo dispositivo.
Controlli: touch, tastiera, pencil, gamepad
Il giocatore controlla Snake con i comandi retrò (il vecchio tastierino del telefono). La versione iOS originale usava dei UIButton trasparenti fissi, che avevo piazzato sopra le foto del vecchio telefono. Un inizio semplice ed efficace.
Purtroppo i pulsanti di iOS avevano un po' di lag (con ritardi imprevedibili nell'input) e ovviamente non si adattavano a schermi di dimensioni diverse. Ho inserito a mano nel codice le nuove coordinate per ogni iPhone che Apple ha lanciato negli ultimi anni.... un lavoro per niente divertente.
Il nuovo motore usa un trucco che ho sviluppato per la versione Android: pulsanti virtuali posizionati dinamicamente. Con le informazioni di scala calcolate dal motore grafico, mantengo dinamicamente una matrice di coordinate X e Y che corrispondono ai pulsanti virtuali. Quando il giocatore tocca lo schermo, il motore calcola il pulsante più vicino con un po' di matematica, il teorema di Pitagora.

Funziona a meraviglia e di fatto trasforma l'intero schermo in un pulsante. Così il gioco è molto più divertente. Oltre al touch ho aggiunto il supporto per la tastiera, così anche chi non ha un touch screen può giocare a Snake.
Mentre lavoravo ai controlli ho scoperto un'altra chicca di HTML5, la GamePad API. Permette a programmatori come me di supportare gamepad, joystick e altri dispositivi di input collegati via USB o Bluetooth.

Supportare gamepad diversi è una sfida, ma comunque divertente. Io ci ho sicuramente perso un'intera giornata "testando"... cioè perfezionando la mia abilità con il formidabile gamepad SNES e con la splendida levetta analogica del controller DualShock. ("Scusa tesoro, sto lavorando...")

Internazionalizzazione
Se leggi questo articolo, probabilmente capisci l'inglese. Ma buona parte del pubblico di Snake '97 non parla inglese. Anzi, ci sono giocatori in più di 30 lingue diverse. Dallo spagnolo al russo, dall'arabo all'ebraico, dal tedesco al giapponese. Dillo e Snake ce l'ha.
Progettare un'interfaccia basata sul testo è difficile se vuoi servire il mondo intero. Nemmeno le icone sono perfette (un'immagine può significare cose diverse). Da UX designer devi pensare a concetti usati ovunque nel mondo. Per Snake ho scelto le icone di un orologio, di un tachimetro, di un altoparlante e di un trofeo. Sono comuni in tutto il mondo e le ho scelte proprio per questo.

La descrizione dell'app è un testo che ho fatto tradurre da un servizio di traduzione professionale. Alcuni altri editori si affidano a Google Translate, ma io so che i risultati sono deprimenti.
Classifica mondiale
Negli anni '90 ti facevi una bella reputazione di strada se facevi un buon punteggio a Snake. Nelle versioni originali di Snake '97 avevi solo il tuo record da battere e su iOS potevi caricare il punteggio su GameCenter.
Per la nuova versione volevo una portata più globale, e ho introdotto la "classifica mondiale". È la nuova classifica integrata che piazza subito la tua partita, confrontando i punteggi di persone di tutto il mondo. Le classifiche sono tre: di sempre, delle ultime 24 ore e dell'ultima ora.

I punteggi vengono elaborati da un incredibile server Intel XEON a 48 core con un sacco di memoria. Ci girano Debian GNU/Linux, MariaDB, NGINX e NodeJS. Nelle ore di punta gestisce più di 10 punteggi al secondo. La configurazione del server merita un articolo tutto suo, che scriverò più avanti: tieni d'occhio questo blog se ti appassionano i big data.

Scaricalo ora
C'è un solo modo per scoprire se il mio lavoro è valido: provalo tu stesso.
Se trovi dei bug, fammelo sapere: qui trovi i miei contatti.
