domenica 4 gennaio 2015

Costruzione del Breakout con il canvas.

Ecco, seguendo un tutorial ho realizzato l'abbozzo del videogiochino della pallina che deve rompere i mattoncini.
Per il momento ho realizzato solo la pallina e la racchetta.
Ora mi analizzo la struttura del giochino... Abbiamo alcune funzioni semplici che potrebbero essere anche messe su un file a parte.
Ho già linkato un file di codice Javascript per la sola funzione $ che evita di dover scrivere document.getElementById, e potrei linkare anche un altro file con queste funzioni.
Ma vediamo se sono "isolabili"...

Il codice intero è questo:
<!DOCTYPE html>
<html>
<head>
<script src="funzioni2.js"></script>

<script>
var canvas;
var ctx;
x=150;
y=150;
var dx=2;
var dy=4;
var WIDTH;
var HEIGHT;

var paddlex;
var paddlew;
var paddleh;


var rightDown=false;
var leftDown=false;

var intervallo;
function inizia(){
	
	//creiamo la base del contesto.
	canvas=$("canvas");
	ctx=canvas.getContext("2d");
	WIDTH=canvas.width;
	HEIGHT=canvas.height;
	
	
	paddlex=WIDTH/2-100;
	paddleh=10;
	paddlew=75;
	
	//funzione setInterval
	intervallo=setInterval(draw,15);
		
}

document.onkeydown=OnKeyDown;
document.onkeyup=OnKeyUp;

function OnKeyDown(evt){

	if (evt.keyCode==39) rightDown=true;
	else if(evt.keyCode==37) leftDown=true;	
}

function OnKeyUp(evt){
	if (evt.keyCode==39) rightDown=false;
	else if (evt.keyCode==37) leftDown=false;
}

function circle(x,y,r){
	ctx.fillStyle="red";
	ctx.beginPath();
	ctx.arc(x,y,r,0,Math.PI*2,true);
	ctx.closePath();
	ctx.fill();
}

function rect(x,y,w,h){
	ctx.beginPath();
	ctx.rect(x,y,w,h);
	ctx.closePath();
}

function clear(){
	ctx.clearRect(0,0,WIDTH,HEIGHT);
}

function draw() {
  	clear();
  	circle(x,y,10);
  	if(rightDown) paddlex+=5;
  	if(leftDown) paddlex-=5;
  	
  	ctx.fillStyle="blue";
  	rect(paddlex,HEIGHT-paddleh,paddlew,paddleh);
  	if(x+dx<0 || x+dx>WIDTH) 
  		dx=-dx;
  	if(y+dy<0)
  		dy=-dy;
  	else if(y+dy>HEIGHT){
	  	if(x>paddlex && x<(paddlex+paddlew))
	  		dy=-dy;
	  	else{
	  		clearInterval(intervallo);
	  		alert("Game over!");
	  		window.location.reload();
  		}
   }
	  	
  	
  		
  	ctx.fill();
  	x+=dx;
  	y+=dy;
}
	




window.addEventListener("load",inizia);
</script>
</head>
<body>

<canvas id="canvas" width="800" height="500" style="border:3px solid maroon"></canvas>

</body>
</html>


Abbiamo:
Funzione circle che traccia un cerchio:
function circle(x,y,r){
	ctx.fillStyle="red";
	ctx.beginPath();
	ctx.arc(x,y,r,0,Math.PI*2,true);
	ctx.closePath();
	ctx.fill();
}
Ecco, qui c'è un elemento che imposta il fillStyle e che va eliminato dalla funzione, oppure va compreso mettendo il colore come parametro.
Scegliamo la seconda e riscriviamo:
function circle(x,y,r,colore){
	ctx.fillStyle=colore;
	ctx.beginPath();
	ctx.arc(x,y,r,0,Math.PI*2,true);
	ctx.closePath();
	ctx.fill();
}
Provandola, con l'accortezza di aggiungere il colore fra i parametri quando si chiama la funzione,
function draw() {
  	clear();
  	circle(x,y,10,"green");
  	if(rightDown) paddlex+=5;
  	if(leftDown) paddlex-=5;
....
....
(ho cambiato colore per verificare bene il funzionamento) funziona!
La possiamo togliere dal codice e immettere in un file a parte, che va linkato al codice della pagina.
Lo chiamo "funzioniCanvas.js" e lo linko:
<!DOCTYPE html>
<html>
<head>
<script src="funzioni2.js"></script>
<script src="funzioniCanvas.js"></script>

Stessa cosa posso fare con la funzione rect che traccia un rettangolo:

function rect(x,y,w,h){
	ctx.beginPath();
	ctx.rect(x,y,w,h);
	ctx.closePath();
}
In questo caso il codice per il colore non è incluso nella funzione, ma è scritto a parte prima di chiamare la funzione.
Potrei fare la stessa scelta che per la funzione che traccia un cerchio, e includere il colore come parametro...

function rect(x,y,w,h,colore){
	ctx.fillStyle=colore;
	ctx.beginPath();
	ctx.rect(x,y,w,h);
	ctx.closePath();
	ctx.fill();
}
e funziona.
Tolgo questa funzione e la metto nel file di codice a parte.
E funziona!
La funzione clear che ripulisce il canvas consentendo l'effetto di animazione, posso portarla nel file di codice.
Questa però usa due variabili, che porto anch'esse nel file a parte:
function clear(){
	ctx.clearRect(0,0,WIDTH,HEIGHT);
}
E funziona ancora tutto.
Ora ci sono le funzioni che stabiliscono se sia stato premuto il tasto destra o sinistra. Queste mi sembrano sufficientemente generalizzabili da poterle portare nel file a parte: settano delle variabili booleane a seconda che sia stato premuto il tasto freccia destra o freccia sinistra, e affidano queste funzioni agli eventi onkeydown del documento HTML.
Fanno uso di due variabili booleane, che porto anch'esse sul file di codice.
var rightDown=false;
var leftDown=false;

document.onkeydown=OnKeyDown;
document.onkeyup=OnKeyUp;

function OnKeyDown(evt){

	if (evt.keyCode==39) rightDown=true;
	else if(evt.keyCode==37) leftDown=true;	
}

function OnKeyUp(evt){
	if (evt.keyCode==39) rightDown=false;
	else if (evt.keyCode==37) leftDown=false;
}


Ho ridotto quasi all'osso la cosa.
Ma potrei anche portare nel codice le procedure che "prendono possesso" del canvas e del contesto, tanto più che anch'esse usano variabili che vi ho già portato:
function inizia(){
	
	//creiamo la base del contesto.
	canvas=$("canvas");
	ctx=canvas.getContext("2d");
	WIDTH=canvas.width;
	HEIGHT=canvas.height;
....
La riscrivo come InitContext...
function initContext(nome){
	canvas=$(nome);
	ctx=canvas.getContext("2d");
	WIDTH=canvas.width;
	HEIGHT=canvas.height;
}
richiamandola dalla funzione iniziale:
function inizia(){
	
	initContext("canvas");
	
	
	paddlex=WIDTH/2-100;
	paddleh=10;
	paddlew=75;
	
	//funzione setInterval
	intervallo=setInterval(draw,15);
		
}
E quindi la porto sul file di codice insieme alle variabili che usa:
var canvas;
var ctx;

function initContext(nome){
	canvas=$(nome);
	ctx=canvas.getContext("2d");
	WIDTH=canvas.width;
	HEIGHT=canvas.height;
}
e funziona!
Io metterei anche una routine che inizializza tutte le variabili.
Prima dichiaro tutte le variabili, quindi le inizializzo in una funzione apposita:
//coordinate della palla
var x;
var y;
var dx;
var dy;

//coordinate della racchetta
var paddlex;
var paddlew;
var paddleh;

var intervallo;
function initVariables(){
	x=100;
	y=100;
	dx=2;
	dy=4;
	
	paddlew=75;
	paddleh=10;
	paddlex=WIDTH/2-120;
}

Nessun commento:

Posta un commento