Per prima cosa prepariamo l'occorrente per lo sviluppo: Un editor di testi ! Tutto quà ? Beh, può sembrare poco ma non è necessario chissà quale IDE di sviluppo per creare qualcosa di funzionante...
Il gioco che ci apprestiamo a realizzare è il Pong, una pietra miliare della storia dei videogame. Cronometro alla mano iniziamo creando il file index.html che conterrà la pagina container del Canvas e il richiamo ai sorgenti del gioco:
<html> <head> <title> Pong in HTML5 </title> </head> <body onLoad=" init(); "> <center> <canvas id="canvas" width="500" height="350" style=" cursor:none; background-color:#333; "> Attenzione, questo browser non supporta i canvas.All'interno del parametro onLoad del body inseriamo la funzione che verrà eseguita appena la pagina sarà caricata completamente nel browser.</canvas> </center> <script src="./game.js"></script> </body> </html>
L'unica vera novità riguarda l'elemento Canvas ossia una finestra grafica che contiene la schermata del nostro gioco. Vediamo ora cosa inserire nel file game.js che contiene tutto il codice sorgente Javascript:
function gameLoop() { aggiornaLogica(); disegnaScena(); } function init(){ canvas.addEventListener('mousemove', mousemove, false); canvas.addEventListener('click', mouseclick, false); // Ripete il gameLoop() ogni 20 millisecondi intervallo = window.setInterval(gameLoop,20); } // Dichiarazione variabili globali canvas = document.getElementById("canvas"); contesto = canvas.getContext("2d"); var scorea = 0, scoreb = 0; var ballx = (canvas.width / 2); var bally = (canvas.height / 2); var ballvx = 0, ballvy = 0; var posy = 150; var cpuy = 100;Come prima cosa si dichiara un elemento Canvas e si acquisisce il contesto 2D inserendolo nella variabile globale contesto.
Le variabili successive servono a memorizzare alcuni dati di gioco come la posizione della pallina e il punteggio di partenza. All'interno della funzione init (che come ricordo viene eseguita al termine del caricamento della pagina) di dichiara un EventListener sul click del mouse e sul suo movimento.
Si procede poi a dichiarare l'esecuzione della funzione gameLoop ogni 20 millisecondi. Ma vediamo ora le funzioni di controllo del mouse:
function mousemove (ev) { if (ev.layerX || ev.layerX == 0) { // Firefox posy = ev.layerY; } else if (ev.offsetX || ev.offsetX == 0) { // Opera & Chrome posy = ev.offsetY; } } function mouseclick (ev) { if (ballvx == 0) { ballvx = 10; ballvy = 0.4; } }
La pressione del mouse determinerà semplicemente il lancio della pallina all'inizio del gioco, mentre l'evento di movimento del mouse aggiorna la coordinata Y della racchetta.
Vediamo ora la funzione di disegno della scena grafica:
function disegnaScena() { // pulisco il canvas contesto.clearRect(0,0,canvas.width,canvas.height); // definisco lo stile di riempimento contesto.fillStyle = "#fff"; // disegno le barre contesto.fillRect(20,posy - 40,10,80); contesto.fillRect(canvas.width - 30,cpuy - 40,10,80); // disegno la pallina contesto.fillRect(ballx,bally,8,8); // scrivo i punteggi contesto.fillText("PLAYER: " + scorea,40,20); contesto.fillText("CPU: " + scoreb,canvas.width - 80,20); }Qui vediamo il comando che cancella la schermata di gioco, poi dopo viene definito lo stile di riempimento bianco per disegnare gli elementi grafici composti da 3 rettangoli.
Infine vengono tracciati i punteggi del computer del del giocatore. Vediamo per terminare la funzione di gestione della logica del gioco:
function aggiornaLogica() { // controllo cpu if (cpuy < bally) cpuy +=6; if (cpuy > bally) cpuy -=6; // aggiorno dati e posizioni degli oggetti nella scena if (posy < 40) posy = 40; if (posy > canvas.height - 40) posy = canvas.height - 40; if (cpuy < 40) cpuy = 40; if (cpuy > canvas.height - 40) cpuy = canvas.height - 40; ballx += ballvx; bally += ballvy; // URTI PALLINA if ((ballvy > 0) && (bally >= canvas.height - 3)) ballvy = -ballvy; if ((ballvy < 0) && (bally <= 3)) ballvy = -ballvy; if ((ballvx > 0) && (ballx >= canvas.width - 30) && (ballx <= canvas.width - 15)) { if ((bally >= cpuy - 40) && (bally <= cpuy + 40)) { ballvx = - ((Math.random() * 5) + 10); ballvy = (Math.random() * 16) - 8; } } if (ballx > canvas.width) { scorea ++; ballx = (canvas.width / 2); bally = (canvas.height / 2); ballvx = 0; ballvy = 0; } // URTI USER if ((ballvx < 0) && (ballx >= 25) && (ballx <= 40)) { if ((bally >= posy - 40) && (bally <= posy + 40)) { ballvx = ((Math.random() * 5) + 10); ballvy = (Math.random() * 16) - 8; } } if (ballx < 0 ) { scoreb ++; ballx = (canvas.width / 2); bally = (canvas.height / 2); ballvx = 0; ballvy = 0; } }Ad ogni ciclo del gameloop la posizione della pallina viene incrementata di un valore arbitrario.
Questa funzione all'apparenza più complessa non fa altro che confrontare la posizione X e Y della pallina per gestire i rimbalzi e l'eventuale punto assegnato quando si superano i limiti orizzontali della schermata.
Una volta effettuato il punto la pallina torna nella posizione centrale in attesa del click del mouse. Il gioco è fatto, seppur molto semplice e poco ottimizzato questo Pong si realizza in pochissimo tempo ed è un buon esempio per iniziare ad avvicinarsi alla programmazione di giochi basati su Canvas.