Introduzione
Nell'estate del 2010 abbiamo creato Sand Trap, un gioco con cui abbiamo partecipato a un concorso di giochi HTML5 per cellulari. Tuttavia, la maggior parte dei telefoni cellulari mostrava solo una parte del gioco o lo rendeva troppo piccolo, rendendolo completamente non giocabile. Per questo motivo, ci siamo impegnati a fare in modo che il gioco si adatti in modo fluido a qualsiasi risoluzione. Dopo un po' di riprogrammazione e l'utilizzo delle idee descritte in questo articolo, abbiamo creato un gioco scalabile su qualsiasi browser moderno, che fosse eseguito su un computer o un dispositivo mobile.


Questo approccio ha funzionato bene per Sand Trap, quindi abbiamo utilizzato lo stesso metodo nel nostro ultimo gioco, Thwack!. Il gioco regola automaticamente le risoluzioni dello schermo in base alle finestre a schermo intero e di dimensioni personalizzate, come mostrato negli screenshot di seguito.
Per implementare questa funzionalità è stato necessario utilizzare sia CSS che JavaScript. L'utilizzo di CSS per riempire l'intero schermo è banale, ma il CSS non consente di mantenere lo stesso rapporto larghezza/altezza per evitare lo stiramento della tela e dell'area di gioco. È qui che entra in gioco JavaScript. Puoi ridimensionare gli elementi del documento con JavaScript e attivare il ridimensionamento sugli eventi della finestra.
Preparazione della pagina
Il primo passaggio consiste nel designare l'area della pagina in cui si svolgerà il gioco. Se lo includi come blocco div, puoi inserire altri tag o un elemento canvas al suo interno. Se li configuri correttamente, questi elementi secondari erediteranno la scalabilità del blocco div principale.
Se la tua area di gioco è composta da due parti, un'area di gioco e un'area per il conteggio dei punti, potrebbe avere il seguente aspetto:
<div id="gameArea">
<canvas id="gameCanvas"></canvas>
<div id="statsPanel"></div>
</div>
Una volta creata una struttura di base del documento, puoi assegnare a questi elementi alcune proprietà CSS per prepararli al ridimensionamento. Molte delle proprietà CSS per "gameArea" vengono manipolate direttamente da JavaScript, ma per funzionare, devi configurare alcune altre proprietà CSS, a partire dal blocco div gameArea principale:
#gameArea {
position: absolute;
left: 50%;
top: 50%;
}
In questo modo, l'angolo in alto a sinistra della tela si trova al centro dello schermo. La funzione di ridimensionamento automatico JavaScript descritta nella sezione successiva manipola proprietà CSS aggiuntive per ridimensionare l'area di gioco e centrarla nella finestra.
Poiché l'area di gioco viene ridimensionata automaticamente in base alle dimensioni della finestra, non è necessario specificare le dimensioni in pixel per gli elementi secondari del blocco div gameArea, ma in percentuale. I valori in pixel non consentono agli elementi interni di ridimensionarsi con il div principale man mano che cambia. Tuttavia, può essere utile iniziare con i pixel e poi convertirli in percentuali una volta ottenuto un layout che ti piace.
Per questo esempio, inizia con un'area di gioco di 300 pixel di altezza e 400 pixel di larghezza. La tela copre l'intera area di gioco e un riquadro delle statistiche semitrasparente è visualizzato nella parte inferiore con un'altezza di 24 pixel, come mostrato nella Figura 1.

La traduzione di questi valori in percentuali rende la tela larga al 100% e alta al 100% (della gameArea, non della finestra). Se dividi 24 per 300, l'altezza del riquadro delle statistiche è pari all'8% e, poiché coprirà la parte inferiore dell'area di gioco, la sua larghezza sarà pari al 100%, come mostrato nella Figura 2.

Ora che hai determinato le dimensioni dell'area di gioco e dei relativi elementi secondari, puoi mettere insieme le proprietà CSS per i due elementi interni come segue:
#gameCanvas {
width: 100%;
height: 100%;
}
#statsPanel {
position: absolute;
width: 100%;
height: 8%;
bottom: 0;
opacity: 0.8;
}
Ridimensionamento del gioco
Ora è tutto pronto per creare una funzione per gestire il ridimensionamento della finestra. Innanzitutto, recupera un riferimento all'elemento del documento gameArea principale.
var gameArea = document.getElementById('gameArea');
Poiché non ti interessa la larghezza o l'altezza esatta, la prossima informazione da impostare è il rapporto tra larghezza e altezza. Utilizzando il riferimento precedente di un'area di gioco di 400 pixel di larghezza e 300 pixel di altezza, sai che vuoi impostare il formato con 4 unità di larghezza e 3 unità di altezza.
var widthToHeight = 4 / 3;
Poiché questa funzione viene chiamata ogni volta che la finestra viene ridimensionata, devi anche acquisire le nuove dimensioni della finestra per poter modificare quelle del gioco in modo che corrispondano. Per trovarlo, utilizza le proprietà innerWidth e innerHeight della finestra.
var newWidth = window.innerWidth;
var newHeight = window.innerHeight;
Così come hai determinato il rapporto tra larghezza e altezza che preferisci, ora puoi determinare il rapporto tra larghezza e altezza corrente della finestra:
var newWidthToHeight = newWidth / newHeight;
In questo modo puoi decidere se far sì che il gioco occupi lo schermo in verticale o in orizzontale, come mostrato nella Figura 3.

Se la forma dell'area di gioco che vuoi creare è più larga della forma della finestra (e l'altezza è inferiore), devi riempire la finestra orizzontalmente e lasciare dei margini in alto e in basso. Analogamente, se la forma dell'area di gioco che vuoi utilizzare è più alta di quella della finestra (e la larghezza è più stretta), devi riempire la finestra verticalmente e lasciare dei margini a sinistra e a destra.
Per farlo, testa il rapporto larghezza/altezza che preferisci con quello della finestra corrente e apporta le modifiche necessarie come segue:
if (newWidthToHeight > widthToHeight) {
// window width is too wide relative to desired game width
newWidth = newHeight * widthToHeight;
gameArea.style.height = newHeight + 'px';
gameArea.style.width = newWidth + 'px';
} else { // window height is too high relative to desired game height
newHeight = newWidth / widthToHeight;
gameArea.style.width = newWidth + 'px';
gameArea.style.height = newHeight + 'px';
}
Ora che hai regolato la larghezza e l'altezza dell'area di gioco, devi centrarla inserendo un margine negativo in alto pari alla metà dell'altezza e a sinistra pari alla metà della larghezza. Ricorda che il CSS posiziona già l'angolo in alto a sinistra dell'elemento div gameArea esattamente al centro della finestra, quindi l'area di gioco viene centrata nella finestra:
gameArea.style.marginTop = (-newHeight / 2) + 'px';
gameArea.style.marginLeft = (-newWidth / 2) + 'px';
Inoltre, ti consigliamo di regolare automaticamente le dimensioni dei caratteri. Se tutti gli elementi secondari utilizzano em, puoi semplicemente impostare la proprietà CSS fontSize del blocco div gameArea su un valore determinato dalle sue dimensioni.
gameArea.style.fontSize = (newWidth / 400) + 'em';
Infine, devi fare in modo che le dimensioni del disegno della tela corrispondano alla nuova larghezza e altezza. Tieni presente che il resto del codice di gioco deve mantenere le dimensioni del motore di gioco separate dalle dimensioni del disegno della tela per adattarsi a una risoluzione della tela dinamica.
var gameCanvas = document.getElementById('gameCanvas');
gameCanvas.width = newWidth;
gameCanvas.height = newHeight;
Pertanto, la funzione di ridimensionamento completata potrebbe avere il seguente aspetto:
function resizeGame() {
var gameArea = document.getElementById('gameArea');
var widthToHeight = 4 / 3;
var newWidth = window.innerWidth;
var newHeight = window.innerHeight;
var newWidthToHeight = newWidth / newHeight;
if (newWidthToHeight > widthToHeight) {
newWidth = newHeight * widthToHeight;
gameArea.style.height = newHeight + 'px';
gameArea.style.width = newWidth + 'px';
} else {
newHeight = newWidth / widthToHeight;
gameArea.style.width = newWidth + 'px';
gameArea.style.height = newHeight + 'px';
}
gameArea.style.marginTop = (-newHeight / 2) + 'px';
gameArea.style.marginLeft = (-newWidth / 2) + 'px';
var gameCanvas = document.getElementById('gameCanvas');
gameCanvas.width = newWidth;
gameCanvas.height = newHeight;
}
Ora vuoi che questi aggiustamenti vengano apportati automaticamente ogni volta che la finestra viene ridimensionata o, nel caso dei dispositivi mobili, l'orientamento dello schermo viene modificato. Gestisci questi eventi facendo in modo che chiamino la funzione resizeGame() nel seguente modo:
window.addEventListener('resize', resizeGame, false);
window.addEventListener('orientationchange', resizeGame, false);
Se la finestra è stata ridimensionata in modo che sia troppo alta o se l'orientamento dello schermo è verticale, la larghezza sarà pari al 100% della finestra. Se la finestra è stata ridimensionata in modo che sia troppo larga o se l'orientamento dello schermo è orizzontale, l'altezza sarà pari al 100% della finestra. La dimensione rimanente viene ridimensionata in base alle proporzioni predeterminate di larghezza e altezza.
Riepilogo
Gopherwood Studios ha utilizzato versioni di questa struttura per tutti i suoi giochi HTML5 e si è dimostrata molto utile per adattarsi a più risoluzioni dello schermo e a vari dispositivi mobili. Inoltre, con l'aiuto di un browser a schermo intero, i nostri giochi web offrono un'esperienza immersiva più simile ai giochi tradizionali per computer rispetto a molti giochi basati su browser. Non vediamo l'ora di introdurre ulteriori innovazioni nei giochi web man mano che HTML5 e le tecnologie web continuano a evolversi.