Animazione di menu di gioco e transizioni di schermate in HTML5 una guida per sviluppatori Flash

Lo sviluppo di HTML5 e Flash può avere molto in comune, ma come sviluppatore Flash ho comunque trovato che è un compito monumentale riapprendere le mie vecchie competenze in HTML5. In questo tutorial, ti mostrerò come ho creato un menu animato e la transizione dello schermo per un gioco shoot-'-up HTML5.


Anteprima del risultato finale

Dai un'occhiata al risultato a cui lavoreremo:


Clicca per provare la demo

Nota lo sfondo a scorrimento, le navi che appaiono e ruotano su entrambi i lati di ciascuna voce di menu e il modo in cui lo schermo sfuma di nero quando selezioni un'opzione.


introduzione

HTML5 e JavaScript sono simili a ActionScript in molti modi; c'è molta sovrapposizione nella sintassi, negli ascoltatori di eventi e nei metodi. Tuttavia ci sono alcune differenze molto distinte che tratterò in questo tutorial:

  • Forme di disegno
  • Disegno di immagini
  • Utilizzando intervalli
  • Animazione
  • Eventi del mouse
  • Aggiunta del supporto per più browser

Qualcosa da notare è che questo tutorial utilizza principalmente immagini che possono essere scaricate con il codice sorgente oppure è possibile utilizzare le proprie immagini, se lo si desidera (è necessario conoscere le larghezze e le altezze).


Passaggio 1: impostazione

La prima cosa che dovremo fare è aggiungere il elemento all'interno del corpo di un file HTML, quindi creane uno chiamato ShootEmUp.html e inserisci quanto segue:

    Sparatutto    

Il tuo browser non supporta HTML5!

Le linee evidenziate inseriscono l'elemento canvas, che renderà il nostro menu attuale. Vedi questo tutorial per una guida su tela da zero.

È già quasi ora di iniziare a scrivere codice JavaScript! Abbiamo due opzioni su dove può andare il codice; Può essere scritto all'interno dell'HTML all'interno

Il prossimo passo sarà creare quattro variabili per fare facilmente riferimento all'elemento canvas.

 var canvas = document.getElementById ("myCanvas"); var context = canvas.getContext ("2d"); var width = canvas.getAttribute ('width'); var height = canvas.getAttribute ('height');

Per prima cosa abbiamo fatto riferimento al MyCanvas variabile e impostarlo in modo che punti all'elemento canvas HTML. Un'altra variabile chiamata contesto è stato creato per ottenere la dimensionalità della tela (2D). Simile a Flash stiamo creando le ultime due variabili, larghezza e altezza, per semplificare il processo di accesso alle proprietà di larghezza e altezza del canvas.


Passaggio 2: caricamento e disegno delle immagini

Come in ActionScript, creeremo istanze delle nostre immagini.

 var bgImage = new Image (); var logoImage = new Image (); var playImage = new Image (); var instructImage = new Image (); var settingsImage = new Image (); var creditsImage = new Image (); var shipImage = new Image ();

Manca una parte cruciale del codice per ogni istanza: il percorso sorgente! Ho salvato tutte le immagini nella cartella "Immagini" all'interno della stessa directory del file HTML, quindi:

 shipImage.src = "Immagini / ship.png"; bgImage.src = "Immagini / Background.png"; logoImage.src = "Immagini / logo.png"; playImage.src = "Immagini / play.png"; instructImage.src = "Immagini / istruzioni.png"; settingsImage.src = "Immagini / impostazioni.png"; creditsImage.src = "Immagini / credits.png";

Prima di disegnare le immagini sulla tela creiamo quattro array per mantenere le posizioni e le dimensioni dei pulsanti (playImage, instructImage, settingsImage, creditsImage). Questi array verranno utilizzati in seguito per creare una funzione di mouse over.

 var buttonX = [192,110,149,160]; var buttonY = [100,140,180,220]; var buttonWidth = [96,260,182,160]; var buttonHeight = [40,40,40,40];

Ora possiamo disegnare le immagini sulla tela; questo può essere fatto all'interno di un onload funzione per ogni immagine, ma non è necessario includere una funzione di caricamento: possiamo semplicemente usarla drawImage ().

 bgImage.onload = function () context.drawImage (bgImage, 0, 0); ; logoImage.onload = function () context.drawImage (logoImage, 50, -10);  playImage.onload = function () context.drawImage (playImage, pulsanteX [0], pulsanteY [0]);  instructImage.onload = function () context.drawImage (instructImage, buttonX [1], buttonY [1]);  settingsImage.onload = function () context.drawImage (settingsImage, buttonX [2], buttonY [2]);  creditsImage.onload = function () context.drawImage (creditsImage, buttonX [3], buttonY [3]); 

Se testato ora, dovresti vedere un'immagine statica di un menu in cui presto respireremo la vita. La nave non è stata disegnata con il resto delle immagini perché la disegneremo più tardi in un evento del mouse. A proposito, se non lo hai fatto finora, mantieni le tue variabili raggruppate in alto e fai lo stesso con le funzioni.


Passaggio 3: animazione attraverso intervalli

JavaScript non ha un onEnterFrame () equivalente, ma possiamo facilmente creare il nostro attraverso l'uso di un intervallo (timer).

 var frames = 30; var timerId = 0; timerId = setInterval (aggiornamento, 1000 / frame);

Potresti essere confuso su come funziona l'intervallo, quindi ti spiegherò brevemente. L'intervallo chiama la funzione aggiornare() ogni (1000 /montatura) millisecondi per creare una frequenza di aggiornamento uniforme. Il valore di montatura controlla i fps; Se montatura è 25 allora il browser proverà a chiamare aggiornare() ogni (1000/25 =) 40 millisecondi.

Il nostro prossimo passo ovvio è creare la funzione aggiornare()

 function update () clear (); mossa(); disegnare(); 

Sono state appena chiamate altre tre funzioni. chiaro() è usato per cancellare la tela perché diversamente dal flash la tela funziona come mettere adesivi su una lavagna; le immagini non possono essere spostate dopo che sono state posizionate. La prossima funzione, mossa(), è usato per cambiare i valori delle variabili che vengono usati con le immagini. Finalmente disegnare() è chiamato a mettere quegli "adesivi".

 funcion clear () context.clearRect (0, 0, width, height); 

In parole semplici, questo codice cancella tutto all'interno del rettangolo che è la dimensione della tela e viene disegnato da (0,0), l'angolo in alto a sinistra. Ciò significa che cancella l'intera tela visibile.

Prima di passare alla funzione successiva, è necessario introdurre due variabili. backgroundY sarà la variabile per la posizione y dell'immagine di sfondo e velocità sarà usato per sottrarre da backgroundY ogni ciclo di aggiornamento.

 var backgroundY = 0; var speed = 1;

L'effetto che stiamo per produrre è uno sfondo a scorrimento continuo. L'immagine è composta da due identiche immagini starfield, una sopra l'altra, in un'immagine più grande (l'immagine è il doppio dell'altezza della tela). Sposteremo lentamente l'immagine fino a quando la seconda metà non sarà completamente visibile e quindi ripristineremo la posizione dell'immagine nella prima metà.

 function move () backgroundY - = speed; if (backgroundY == -1 * height) backgroundY = 0; 

Finalmente abbiamo il disegnare() funzione. Tutte le immagini verranno ridisegnate, ma una modifica da notare è che il bgImageIl valore di y è stato sostituito con la variabile backgroundY.

 context.drawImage (bgImage, 0, backgroundY); context.drawImage (logoImage, 50, -10); context.drawImage (playImage, buttonX [0], pulsanteY [0]); context.drawImage (instructImage, buttonX [1], buttonY [1]); context.drawImage (settingsImage, buttonX [2], buttonY [2]); context.drawImage (creditsImage, buttonX [3], buttonY [3]);

Prova ora e ammira lo sfondo scorrevole.


Passaggio 4: controllo della posizione del mouse

Una cosa l'HTML5 manca il supporto per gli ascoltatori di eventi di immagini, il che significa che non possiamo semplicemente scrivere playImage.mouseover = function () . Invece, dobbiamo ottenere la posizione del mouse rispetto alla tela e capire se si tratta di un oggetto.

 var mouseX; var mouseY; canvas.addEventListener ("mousemove", checkPos);

Le due variabili introdotte verranno utilizzate per ottenere la posizione corrente del mouse. Abbiamo aggiunto un listener di eventi, come in ActionScript, che chiama la funzione checkPos () ogni volta che il mouse si muove.

 function checkPos (mouseEvent) mouseX = mouseEvent.pageX - this.offsetLeft; mouseY = mouseEvent.pageY - this.offsetTop; 

Se hai avvisato i valori di mouseX e mouseY ogni volta che muovi il mouse ottieni la posizione corretta. Ma c'è un problema: non tutti i moderni browser desktop supportano questo metodo. Per ovviare a questo problema, possiamo usare invece il piccolo hack:

 if (mouseEvent.pageX || mouseEvent.pageY == 0) mouseX = mouseEvent.pageX - this.offsetLeft; mouseY = mouseEvent.pageY - this.offsetTop;  else if (mouseEvent.offsetX || mouseEvent.offsetY == 0) mouseX = mouseEvent.offsetX; mouseY = mouseEvent.offsetY; 

Controlla se il browser utilizza le proprietà "page" o "offset" per restituire la posizione del mouse e regola i valori (se necessario) per ottenere la posizione del mouse rispetto alla tela.

Ora ricorda quella nave che abbiamo istanziato, ma non abbiamo disegnato? Prenderemo quell'immagine statica, girarla e farla apparire ogni volta che passiamo il mouse sui pulsanti!

 var shipX = [0,0]; var shipY = [0,0]; var shipWidth = 35; var shipHeight = 40; var shipVisible = false; var shipSize = shipWidth; var shipRotate = 0;

Le prime quattro variabili sono le stesse di prima (abbiamo due posizioni perché ci saranno due navi). Il shipVisible la variabile verrà impostata su true quando il mouse si trova su un pulsante. Quanto a shipSize e shipRotate, saranno usati per scalare la nave verticalmente e riposizionarla per dare l'illusione che stia girando. Tieni presente che le immagini vengono ridimensionate da destra a sinistra.

 per (i = 0; i < buttonX.length; i++) if(mouseX > buttonX [i] && mouseX < buttonX[i] + buttonWidth[i]) if(mouseY > bottoneY [i] && mouseY < buttonY[i] + buttonHeight[i])  else  

Aggiungi il codice nel checkPos () funzione. Per prima cosa passiamo in rassegna i pulsanti che ci sono (ho capito il valore usando buttonX.length). Successivamente confrontiamo il mouseX per vedere se è maggiore del pulsante corrente buttonX e meno del suo buttonX + buttonWidth - cioè entro i limiti orizzontali del pulsante. Ripetiamo il processo in un'altra istruzione if per i valori Y. Se questo è tutto vero, il mouse deve trovarsi sopra un pulsante, quindi impostare shipVisible a vero:

 shipVisible = true;

E dentro il vuoto altro la dichiarazione lo ha impostato falso; verrà quindi chiamato ogni volta che tocchi il mouse da un pulsante:

 shipVisible = false;

Sotto shipVisible = true imposteremo i valori iniziali per il shipX e Shipy, ed esegui tutto il ridimensionamento all'interno della mossa e disegna le funzioni.

 shipX [0] = buttonX [i] - (shipWidth / 2) - 2; shipY [0] = pulsanteY [i] + 2; shipX [1] = buttonX [i] + buttonWidth [i] + (shipWidth / 2); shipY [1] = pulsanteY [i] + 2;

Per la prima shipX, che vogliamo solo alla sinistra del pulsante, impostiamo il valore su (l'X del pulsante corrente - metà della larghezza della nave), e l'ho spostato di oltre 2 pixel verso sinistra per renderlo migliore. Un processo simile viene ripetuto per il primo Shipy. Per il secondo shipX posizioniamo alla (X corrente del pulsante + la larghezza del pulsante + metà della larghezza della nave), e quindi impostiamo la Y come prima.

La parte difficile arriva ora. Dobbiamo scalare la nave e spostarla per compensare il ridimensionamento. All'interno del mossa() funzione scrivere questo Se dichiarazione.

 if (shipSize == shipWidth) shipRotate = -1;  if (shipSize == 0) shipRotate = 1;  shipSize + = shipRotate;

Il codice inizia a sottrarre il valore di shipSize, che verrà usato per ridimensionare l'immagine quando la disegniamo; una volta che raggiunge lo zero, il processo si inverte fino a quando non torna a fondo scala.

Ora possiamo entrare nel disegnare() funzione. Di seguito tutti gli altri metodi di disegno aggiungono la seguente istruzione if.

 if (shipVisible == true) context.drawImage (shipImage, shipX [0] - (shipSize / 2), shipY [0], shipSize, shipHeight); context.drawImage (shipImage, shipX [1] - (shipSize / 2), shipY [1], shipSize, shipHeight); 

Le navi vengono disegnate normalmente ad eccezione delle posizioni X che vengono compensate sottraendo metà della scala attuale.


Passaggio 5: verifica dei clic del mouse

Aggiungi un altro listener di eventi per il mouse e crea una nuova variabile per un secondo intervallo che creeremo.

 var fadeId = 0; canvas.addEventListener ("mouseup", checkClick);

Crea la funzione checkClick ().

 function checkClick (mouseEvent) per (i = 0; i < buttonX.length; i++) if(mouseX > buttonX [i] && mouseX < buttonX[i] + buttonWidth[i]) if(mouseY > bottoneY [i] && mouseY < buttonY[i] + buttonHeight[i])    

Come prima, controlliamo se la posizione del mouse è corretta. Ora dobbiamo creare il nuovo intervallo e interrompere l'altro intervallo e gli ascoltatori di eventi.

 fadeId = setInterval ("fadeOut ()", 1000 / frames); clearInterval (timerId); canvas.removeEventListener ("mousemove", checkPos); canvas.removeEventListener ("mouseup", checkClick);

Niente di nuovo qui tranne che abbiamo bisogno di creare una funzione chiamata dissolvenza(). Abbiamo anche bisogno di creare un'altra variabile chiamata tempo.

 var time = 0.0;
 function fadeOut () context.fillStyle = "rgba (0,0,0, 0,2)"; context.fillRect (0, 0, larghezza, altezza); tempo + = 0,1; if (time> = 2) clearInterval (fadeId); tempo = 0; timerId = setInterval ("update ()", 1000 / frames); canvas.addEventListener ("mousemove", checkPos); canvas.addEventListener ("mouseup", checkClick); 

Ha alcuni nuovi metodi, ma è abbastanza semplice. Dal momento che abbiamo fermato tutti gli ascoltatori di eventi e l'altro intervallo il nostro menu è completamente statico. Quindi stiamo ripetutamente disegnando un rettangolo nero trasparente sopra il menu - senza cancellarlo - per dare l'illusione di svanire.

La variabile tempo viene aumentato ogni volta che viene richiamata la funzione e una volta raggiunto un determinato valore (una volta passati 20 "frame", in questo caso) viene cancellato l'intervallo corrente. Qui resetto il menu, ma è qui che disegneresti una nuova sezione del menu.

Un'ultima cosa da notare è che quando disegni forme sulla tela il fillStyle è impostato con un valore rgb (rosso, verde, blu). Quando vuoi disegnare forme trasparenti, usi rgba (rosso, verde, blu, alfa).

Spero che sia sminuito un po 'del processo di apprendimento per passare dalla semplice programmazione AS3 alla semplice programmazione su tela. Pubblica un commento se hai domande!