5 consigli per sviluppare un HTML5 game

31 ottobre 2013

Mentre Web e marketplace si riempiono di videogiochi di ogni foggia: nuovi giochi, cloni di vecchi classici, cloni dei nuovi migliorati (o peggiorati) e si fanno tentativi più o meno riusciti di trovare il gioco preferito dalla gente, molti sviluppatori si chiedono come meglio investire il proprio tempo per creare questi prodotti.

Dal mio modesto punto di vista iniziare creando browser-game è un buon punto di partenza. Perché?

  • Perché anzitutto abbiamo a disposizione un’immensità di materiale su JavaScript
  • C’è una vasta letteratura anche su HTML5 Canvas, WebGL, SVG etc.
  • Ci sono numerosissimi Framework che ci permettono di sfruttare senza troppa fatica le tecnologie che abbiamo appena citato.
  • E soprattutto ci sono i browser moderni con tutto il necessario per lavorare, testare, provare, debuggare etc. Un esempio per tutti Internet Explorer 11.

Una volta realizzato, il nostro browser game (o HTML5 game che dir si voglia) potrà essere un buon biglietto da visita e attirare visite dei giocatori sul nostro sito. Inoltre abbiamo un trampolino pronto per creare app native per tutte le piattaforme, utilizzando le stesse tecniche… ma questa è un’altra storia.

In questo articolo esaminiamo alcuni punti chiave utili per creare giochi e lo facciamo prendendo spunto da questo articolo di Kai Jäger.

1. Iniziare sempre dalle basi…

Nel primo punto Kai suggerisce subito l’utilizzo di un framework e il suggerimento è da considerarsi assolutamente valido, tuttavia secondo me vale la pena spendere un po’ di tempo per apprendere o consolidare le basi di JavaScript, soprattutto la gestione degli oggetti, e l’API di HTML5 Canvas.

Con questo non intendo dire che bisogna studiare valanghe di libri, ma almeno passare un paio d’ore a farsi un’idea su come affrontare alcuni aspetti:

  • creare una pagina HTML minima che ospiti il nostro gioco
  • disegnare gli oggetti su una scena, basta anche mettere su una semplice forma come un rectFill o caricare una png
  • rappresentare gli oggetti, e qui possiamo sfruttare le proprietà di JavaScript
  • gestire il loop principale del gioco, per questo possiamo anche sfruttare il classico setInterval.
  • gestire l’input dell’utente, per questo basta cercare un po’ di documentazione su eventi come keypressed, sulla gestione del mouse o sui pointer events per il touch.

Per capirci ecco un breve esempio (non completo) di come si può iniziare a lavorare a un clone di PONG.

Un progetto da zero… a zero punto uno

Mettiamo su un file HTML con il minimo necessario per il rendering del canvas:

<!doctype html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<script type="text/javascript" src="game.js"></script>
<style>
html,
body 
{
	margin: 0px; padding: 0px;
	background-color: black;
	overflow: hidden;
	cursor: none;
	color:#fff; /* da cancellare */
}

canvas
{
	position: absolute;
	width: 100%; height: 100%;
	top: 0%; left: 0%;
}
</style>
<title>Canvas Game</title>
</head><body>
<canvas id="gamecanvas" />
</body></html>

Nel file game.js abbiamo tutta la logica del gioco, vediamone alcune parti.

Oggetti sullo schermo

Ecco una possibile rappresentazione delle barrette (qui c’è quella sinistra) e della pallina:

var leftbar = {
	speed: 5, // velocità in px/frame
	x: 0,
	y: 0,
	width: 10,
	height: 20,
	
	draw: function(ctx) {
			// disegnamo la barra sinistra
			ctx.fillStyle = "#fff";
			ctx.fillRect(this.x, this.y, this.width , this.height);
		  }
};

var ball = {
	
	speed: 5,
	x:0, y:0,
	radius:5,
	
	// direzione, inizialmente casuale
	angle: Math.random() * Math.PI * 2,
	
	draw: function(ctx) {
			// disegnamo la barra sinistra
			ctx.fillStyle = "#fff";
			ctx.beginPath();  
			ctx.arc(this.x, this.y, this.radius, 0, Math.PI*2, false);  
			ctx.closePath();  
			ctx.fill(); 
		  },
		  
	move: function(ctx) {
			this.x += Math.cos(this.angle) * this.speed;
		    this.y += Math.sin(this.angle) * this.speed;
		  }
};

Ecco invece come poter sbrigativamente effettuare qualche definizione inizale, il loop e le funzioni di rendering.

// inizializzazione
document.addEventListener("DOMContentLoaded", function() {
    console.log("Documento caricato!"); // debugmsg
	
	
	// Recupero del contesto 2D dell'elemento canvas
	var canvas = document.getElementById("gamecanvas"),
		ctx = canvas.getContext("2d");
	
	console.log("contesto 2d acquisito: " + ctx);
	
	// altezza e larghezza della finestra
	var W = window.innerWidth, 
		H = window.innerHeight;
		
	canvas.width  = W;
	canvas.height = H; 		
		
	// posizionamento delle barrette
	leftbar.x = Math.ceil(W/100*2);
	rightbar.x = Math.ceil(W/100*98);
	leftbar.y = rightbar.y = Math.ceil(H/2 - leftbar.height/2);
	leftbar.width = rightbar.width = Math.ceil(W/100*1); // barretta larga il 2% dello schermo
	leftbar.height = rightbar.height = Math.ceil(H/100*15); // barretta alta il 10% dello schermo
	
	// posizionamento iniziale della palla
	ball.x =  Math.ceil(W/2);
	ball.y =  Math.ceil(H/2);
	ball.radius = Math.ceil(W/100*1);
	
	
	function render() { 
	
		// puliamo lo sfondo
		ctx.fillStyle = "#000";
		ctx.fillRect(0, 0, W, H);
		console.log("puliamo lo sfondo");
		
		
		// disegnamo gli oggetti
		leftbar.draw(ctx);
		rightbar.draw(ctx);
		
		// controlla le collisioni con i bordi
		if ((ball.y-ball.radius < 0) || (ball.y+ball.radius > H))
			ball.angle = 2*Math.PI - ball.angle; 
				
		// aggiorna la posizione della palla
		ball.move(ctx);
		
		// if (ball.collide(leftbar)) console.log('collisione con leftbar');
		// if (ball.collide(rightbar)) console.log('collisione con rightbar');
		
		ball.draw(ctx);		
	}
	
	// primo disegno della scena
	render();
		
	// elaborazione degli eventi della tastiera
	window.onkeydown = function(event) {
		
		switch (event.which) {
		case 38:
			leftbar.y -= leftbar.speed;
			break;
		case 40:
		    leftbar.y += leftbar.speed;
			break;
		default:
			return; // evita di restituire false
		}
		return false;
	};
	
	
	
	// impostazione del loop
	var then = Date.now(); // timestamp iniziale
	setInterval(mainLoop, 50); 
	// la scelta dei 50 ms è per non intasare troppo il processore nel test
	// si può anche mettere 1ms 
	
	
	function mainLoop()
	{
		// timestamp in ms (tempo passato da1l' 1/1/1970 alle 00:00)
		var now = Date.now();
		// differenza tra il momento attuale e il ciclo appena precedente
		var delta = now - then;
		render();

		then = now;
	}
	
});

Si può fare molto meglio, ma è un esercizio utile per prendere contatto con l’ambiente e i pattern basilari utilizzati da tutti i framework: loop, rendering della scena, controlli ed eventi, componenti.

Se vuoi aggiornamenti su 5 consigli per sviluppare un HTML5 game inserisci la tua e-mail nel box qui sotto:
 
X
Se vuoi aggiornamenti su 5 consigli per sviluppare un HTML5 game

inserisci la tua e-mail nel box qui sotto:

Ho letto e acconsento l'informativa sulla privacy

Acconsento al trattamento di cui al punto 3 dell'informativa sulla privacy