Animarea meniurilor jocului și a tranzițiilor ecranului în HTML5 Un ghid pentru dezvoltatorii Flash

Dezvoltarea HTML5 și Flash poate avea multe în comun, dar, în calitate de dezvoltator Flash, am găsit încă o sarcină monumentală de a-mi reînvia cunoștințele vechi în HTML5. În acest tutorial, vă voi arăta cum am creat un meniu animat și o tranziție de ecran pentru un joc HTML5 shoot-'em-up.


Rezultatul final al rezultatelor

Uitați-vă la rezultatul pe care îl vom face:


Faceți clic pentru a încerca demonstrația

Rețineți fundalul de defilare, navele care apar și se rotesc pe fiecare parte a fiecărui element de meniu și modul în care ecranul se estompează la negru atunci când selectați o opțiune.


Introducere

HTML5 și JavaScript sunt similare cu ActionScript în multe feluri; există o mulțime de suprapuneri în sintaxă, ascultători de evenimente și metode. Cu toate acestea, există unele diferențe foarte diferite pe care le voi acoperi în acest tutorial:

  • Forme de desen
  • Desenarea imaginilor
  • Folosind intervalele
  • însuflețitor
  • Mouse-ul evenimentelor
  • Adăugarea de asistență pentru mai multe browsere

Ceva de remarcat este că acest tutorial folosește în principal imagini care pot fi descărcate cu sursa sau puteți folosi propriile imagini dacă vă place (va trebui să cunoașteți lățimile și înălțimile).


Pasul 1: Configurarea

Primul lucru pe care trebuie să-l facem este să adăugăm element în interiorul corpului unui fișier HTML, așa că creați unul numit ShootEmUp.html și introduceți următoarele:

    Impusca-i    

Browserul dvs. nu acceptă HTML5!

Liniile evidențiate inserați elementul de panza, care va face meniul nostru real. Consultați acest tutorial pentru un ghid de pânză de la zero.

Este deja aproape timpul să începeți codarea JavaScript! Avem două opțiuni cu privire la locul în care poate merge codul; Acesta poate fi scris în interiorul HTML-ului

Următorul pas va fi crearea a patru variabile pentru a face referire la elementul de panza cu ușurință.

 var canvas = document.getElementById ("myCanvas"); var context = canvas.getContext ("2d"); var width = canvas.getAttribute ("lățimea"); var height = canvas.getAttribute ("înălțime");

Am menționat mai întâi myCanvas și setați-o să indice elementul HTML canvas. O altă variabilă numită context a fost creat pentru a obține dimensiunile canalului (2D). Similar cu Flash, suntem creați ultimele două variabile, lăţime și înălţime, pentru a simplifica procesul de accesare a proprietăților lățimii și înălțimii panzei.


Pasul 2: Încărcarea și desenarea imaginilor

La fel ca în ActionScript, vom crea instanțe ale imaginilor noastre.

 var bgImage = imagine nouă (); var logoImage = imagine nouă (); var playImage = imagine nouă (); var instructImage = imagine nouă (); var settingsImage = imagine nouă (); var creditsImage = imagine nouă (); var shipImage = imagine nouă ();

Lipsesc o piesă crucială de cod pentru fiecare instanță - calea sursă! Am salvat toate imaginile din directorul "Imagini" din același director ca fișierul HTML, astfel:

 shipImage.src = "Imagini / navă.png"; bgImage.src = "Imagini / Fundal.png"; logoImage.src = "Imagini / logo.png"; playImage.src = "Imagini / play.png"; instructImage.src = "Imagini / instrucțiuni.png"; settingsImage.src = "Imagini / setări.png"; creditsImage.src = "Imagini / credite.png";

Înainte de a desena imaginile pe panza, creați patru tablouri pentru a ține pozițiile și dimensiunile butoanelor (playImage, instructImage, settingsImage, creditsImage). Aceste tablouri vor fi utilizate mai târziu pentru a crea o funcție de mouse peste.

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

Acum putem desena imagini pe pânză; acest lucru se poate face într-un onload pentru fiecare imagine, dar nu trebuie să fie inclusă o funcție de încărcare - putem folosi pur și simplu drawImage ().

 bgImage.onload = funcție () context.drawImage (bgImage, 0, 0); ; logoImage.onload = funcție () context.drawImage (logoImage, 50, -10);  playImage.onload = funcția () context.drawImage (playImage, butonulX [0], butonulY [0]);  instructImage.onload = funcția () context.drawImage (instructImage, butonulX [1], butonulY [1]);  setăriImage.onload = funcție () context.drawImage (setăriImage, butonX [2], butonY [2]);  creditsImage.onload = funcția () context.drawImage (crediteImage, butonulX [3], butonulY [3]); 

Dacă încercați acum, ar trebui să vedeți o imagine statică a unui meniu pe care în curând îl vom respira. Nava nu a fost însoțită de restul imaginilor, deoarece vom trage mai târziu într-un eveniment de șoarece. Apropo, dacă nu ați făcut acest lucru până acum, păstrați variabilele grupate împreună în partea de sus și faceți același lucru cu funcțiile.


Pasul 3: Animarea prin intervale

JavaScript nu are un onEnterFrame () echivalent, dar putem crea cu ușurință propriile noastre prin utilizarea unui interval (temporizator).

 cadrele var = 30; var timerId = 0; timerId = setInterval (actualizare, 1000 / cadre);

S-ar putea să fii confuză cu privire la modul în care funcționează intervalul, așa că voi explica pe scurt. Intervalul numește funcția Actualizați() fiecare (1000 /rame) de milisecunde pentru a crea o rată de reîmprospătare netedă. Valoarea a rame controlează fps-urile; dacă rame este de 25, atunci browserul va încerca să sune Actualizați() fiecare (1000/25 =) 40 de milisecunde.

Următorul nostru pas evident este de a crea funcția Actualizați()

 funcția de actualizare () clar (); mișcare(); a desena(); 

Au mai fost numite alte trei funcții. clar() este folosit pentru a șterge pânza deoarece, spre deosebire de blițul, pânza funcționează ca și cum ați pune autocolante pe o placă; imaginile nu pot fi mutate după ce au fost plasate. Următoarea funcție, mișcare(), este utilizat pentru modificarea valorilor variabilelor care sunt utilizate cu imaginile. In cele din urma a desena() este chemat să pună acele "autocolante".

 funcion clear () context.clearRect (0, 0, lățime, înălțime); 

Puneți simplu, acest cod șterge totul în interiorul dreptunghiului care este dimensiunea pânzei și este extras din (0,0), colțul din stânga sus. Asta înseamnă că curăță întreaga pânză vizibilă.

Înainte de a trece la următoarea funcție, trebuie introduse două variabile. backgroundY va fi variabila pentru poziția y a imaginii de fundal și viteză va fi folosit pentru a scăpa de la backgroundY fiecare ciclu de actualizare.

 var backgroundY = 0; viteza var = 1;

Efectul pe care îl vom produce este un fundal în continuă evoluție. Imaginea este alcătuită din două imagini identice, unul peste celălalt, într-o imagine mai mare (imaginea fiind de două ori înălțimea pânzei). Vom muta lent imaginea până când a doua jumătate este complet vizibilă și apoi vom reseta poziția imaginii înapoi la prima jumătate.

 mutarea funcției () backgroundY - = speed; dacă (backgroundY == -1 * înălțime) backgroundY = 0; 

În cele din urmă avem a desena() funcţie. Toate imaginile vor fi redesenate, însă o singură modificare va fi aceea că bgImagevaloarea lui y a fost înlocuită cu variabila backgroundY.

 context.drawImage (bgImage, 0, backgroundY); context.drawImage (logoImage, 50, -10); context.drawImage (playImage, butonulX [0], butonulY [0]); context.drawImage (instructImage, butonulX [1], butonulY [1]); context.drawImage (setăriImage, butonX [2], butonY [2]); context.drawImage (crediteImage, butonulX [3], butonulY [3]);

Testați acum și admirați fundalul de derulare netedă.


Pasul 4: Verificarea poziției mouse-ului

Un lucru HTML5 lipsește suportul pentru ascultătorii de evenimente de imagine, ceea ce înseamnă că nu putem scrie pur și simplu playImage.mouseover = funcția () . În schimb, trebuie să obținem poziția mouse-ului relativ la pânză și să ne dăm seama dacă este peste un obiect.

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

Cele două variabile introduse vor fi folosite pentru a obține poziția curentă a mouse-ului. Am adăugat un ascultător de evenimente, ca în ActionScript, care apelează funcția checkPos () de fiecare dată când se mișcă mouse-ul.

 funcția checkPos (mouseEvent) mouseX = mouseEvent.pageX - this.offsetLeft; mouseY = mouseEvent.pageY - this.offsetTop; 

Dacă ați alertat valorile mouseX și mousey de fiecare dată când mișcați mouse-ul, veți obține poziția corectă. Dar există o problemă: nu toate browserele de desktop moderne acceptă această metodă. Pentru a depăși această problemă, putem folosi în schimb:

 dacă (mouseEvent.pageX || mouseEvent.pageY == 0) mouseX = mouseEvent.pageX - this.offsetLeft; mouseY = mouseEvent.pageY - this.offsetTop;  altceva dacă (mouseEvent.offsetX || mouseEvent.offsetY == 0) mouseX = mouseEvent.offsetX; mouseY = mouseEvent.offsetY; 

Acest lucru verifică dacă browserul utilizează proprietăți "pagină" sau "offset" pentru a readuce poziția mouse-ului și ajustează valorile (dacă este necesar) pentru a obține poziția mouse-ului față de pânză.

Acum, amintiți-vă că nava am instanced, dar nu a atras? Vom lua acea imagine statică, o vom roti și vom face să apară ori de câte ori știm mouse-ul peste butoane!

 vapor varX = [0,0]; var naY = [0,0]; var shipWidth = 35; var shipHeight = 40; var shipVisible = false; var shipSize = Lățimea navei; var shipRotate = 0;

Primele patru variabile sunt aceleași ca înainte (avem două poziții deoarece vor exista două nave). shipVisible variabila va fi setată atunci când mouse-ul este peste un buton. În ceea ce privește shipSize și shipRotate, ele vor fi utilizate pentru a scala vertical nava și pentru ao repoziționa pentru a da iluzia că se rotește. Rețineți că imaginile sunt scalate de la dreapta la stânga.

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

Adăugați codul în checkPos () funcţie. Mai intai trecem prin butoanele de acolo (mi-am dat seama ca folosesc valoarea buttonX.length). Apoi comparăm mouseX pentru a vedea dacă este mai mare decât butonul curent buttonX și mai puțin decât a lui butonul ButonX + Lățime - adică în limitele orizontale ale butonului. Apoi repetăm ​​procesul în altă instrucțiune if pentru valorile Y. Dacă acest lucru este adevărat, atunci mouse-ul trebuie să fie peste un buton, setat astfel shipVisible la Adevărat:

 shipVisible = true;

Și în gol altfel declarația a pus-o la fals; acesta va fi numit ori de câte ori vă scoateți dintr-un buton:

 shipVisible = false;

Sub shipVisible = adevărat vom seta valorile inițiale pentru shipX și Shipy, și efectuați toate scalarea în cadrul funcțiilor de deplasare și de desen.

 shipX [0] = butonulX [i] - (ShipWidth / 2) - 2; nava [0] = butonul [i] + 2; shipX [1] = butonulX [i] + butonul Width [i] + (ShipWidth / 2); naYY [1] = butonulY [i] + 2;

Pentru primul shipX, pe care o dorim doar la stânga butonului, am setat valoarea la (butonul curent al lui X - jumătate din lățimea navei) și l-am mutat peste 2 pixeli la stânga pentru a face să arate mai bine. Un proces similar este repetat pentru primul Shipy. Pentru al doilea shipX poziționăm la butonul curent (X + cu lățimea butonului + jumătate din lățimea navei) și apoi am setat modelul Y ca înainte.

Partea dificilă vine acum. Trebuie să scarăm nava și să o mutăm pentru a compensa scalarea. În cadrul mișcare() funcția scrie acest lucru dacă afirmație.

 dacă (shipSize == ShipWidth) shipRotate = -1;  dacă (shipSize == 0) shipRotate = 1;  shipSize + = shipRotate;

Codul începe să scadă valoarea lui shipSize, care vor fi utilizate pentru a scala imaginea atunci când o tragem; odată ce atinge zero, procesul se inversează până când este din nou scalarea completă.

Acum ne putem muta în a desena() funcţie. Sub celelalte metode de tragere adăugați următoarea declarație if.

 dacă (shipVisible == true) context.drawImage (ShipImage, shipX [0] - (ShipSize / 2), shipY [0], ShipSize, shipHeight); context.drawImage (ShipImage, shipX [1] - (navăSize / 2), navă [1], navăSize, navă); 

Navele sunt trase în mod normal, cu excepția pozițiilor X compensate prin scăderea jumătății scării actuale.


Pasul 5: Verificarea clicurilor pe mouse

Adăugați un alt ascultător de evenimente pentru mouseup și creați o nouă variabilă pentru un al doilea interval pe care îl vom crea.

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

Creați funcția checkClick ().

 funcția checkClick (mouseEvent) pentru (i = 0; i < buttonX.length; i++) if(mouseX > butonulX [i] && mouseX < buttonX[i] + buttonWidth[i]) if(mouseY > butonulY [i] && mouseY < buttonY[i] + buttonHeight[i])    

Ca și înainte, verificăm dacă poziția mouse-ului este corectă. Acum trebuie să creăm noul interval și să oprim celelalte intervale și ascultători de evenimente.

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

Nimic nou aici, cu excepția faptului că trebuie să creăm o funcție numită fadeOut (). De asemenea, trebuie să creați o altă variabilă numită timp.

 var timp = 0,0;
 funcția fadeOut () context.fillStyle = "rgba (0,0,0, 0,2)"; context.fillRect (0, 0, lățime, înălțime); timp + = 0,1; dacă (timp> = 2) clearInterval (fadeId); timpul = 0; timerId = setInterval ("actualizare ()", 1000 / cadre); canvas.addEventListener ("mousemove", checkPos); canvas.addEventListener ("mouseup", checkClick); 

Ea are câteva metode noi, dar este destul de simplă. Deoarece am oprit toți ascultătorii evenimentului iar celălalt intervalul este complet static. Așadar, redăm în mod repetat un dreptunghi transparent negru pe partea de sus a meniului - fără să îl ștergem - pentru a da iluzia de estompare.

Variabila timp este mărită de fiecare dată când este apelată funcția și odată ce atinge o anumită valoare (odată ce au trecut 20 de cadre), ștergem intervalul curent. Aici am reinițializat meniul, dar aici este locul unde ați desena o nouă secțiune a meniului.

Un ultim lucru de observat este că atunci când desenați forme pe panza stil de completare este setată cu o valoare rgb (roșu, verde, albastru). Când doriți să desenați forme transparente, utilizați rgba (roșu, verde, albastru, alfa).

Sper că este demistificat un pic de proces de învățare pentru trecerea de la programarea AS3 simplă la programarea simplu în panza. Postați un comentariu dacă aveți întrebări!

Cod