Animerende spillmenyer og skjermoverganger i HTML5 En guide for Flash-utviklere

HTML5 og Flash-utvikling kan ha mye til felles, men som en Flash-utvikler har jeg fortsatt funnet det å være en monumental oppgave å gjenopplære mine gamle ferdigheter i HTML5. I denne opplæringen vil jeg vise deg hvordan jeg opprettet en animert meny og skjermovergang for et HTML5-skytespill.


Endelig resultatforhåndsvisning

Ta en titt på resultatet vi skal jobbe for:


Klikk for å prøve demoen

Merk rullingsbakgrunnen, skipene som vises, og roter hver side av hvert menyelement, og måten skjermen faller til svart når du velger et alternativ.


Introduksjon

HTML5 og JavaScript ligner ActionScript på mange måter; Det er mye overlapping i syntaks, hendelselyttere og metoder. Men det er noen svært forskjellige forskjeller som jeg vil dekke i denne opplæringen:

  • Tegningsformer
  • Tegnebilder
  • Bruke intervaller
  • animere
  • Mus Hendelser
  • Legge til støtte for flere nettlesere

Noe å merke seg er at denne opplæringen hovedsakelig bruker bilder som kan lastes ned med kilden, eller du kan bruke dine egne bilder hvis du vil (du må vite bredder og høyder).


Trinn 1: Oppsett

Det første vi må gjøre er å legge til element i kroppen av en HTML-fil, så opprett en kalt ShootEmUp.html og sett inn følgende:

    Skyt dem opp    

Nettleseren din støtter ikke HTML5!

De uthevede linjene setter inn lerretelementet, som vil gjengi vår faktiske meny. Se denne opplæringen for en guide til lerret fra grunnen av.

Det er allerede nesten tid å begynne å kode JavaScript! Vi har to alternativer til hvor koden kan gå; Det kan skrives inne i HTML-en

Vårt neste skritt vil være å skape fire variabler for å referere lerretet enkelt.

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

Vi refererte først til myCanvas variabel og sett den til å peke på HTML-lerretelementet. En annen variabel heter kontekst ble opprettet for å få dimensionalitet på lerretet (2D). I likhet med Flash skaper vi de to siste variablene, bredde og høyde, for å forenkle prosessen med å få tilgang til lerretets bredde- og høydeegenskaper.


Trinn 2: Lasting og tegning av bilder

Som i ActionScript skal vi lage forekomster av bildene våre.

 var bgImage = nytt bilde (); var logoImage = nytt bilde (); var playImage = nytt bilde (); var instructImage = nytt bilde (); var settingsImage = nytt bilde (); var creditsImage = nytt bilde (); var shipImage = nytt bilde ();

Vi mangler et viktig stykke kode for hver forekomst - kildebanen! Jeg lagret alle bildene i mappen 'Bilder' i samme katalog som HTML-filen, så:

 shipImage.src = "Images / ship.png"; bgImage.src = "Images / Background.png"; logoImage.src = "Images / logo.png"; playImage.src = "Images / play.png"; instructImage.src = "Images / instructions.png"; settingsImage.src = "Images / settings.png"; creditsImage.src = "Images / credits.png";

Før vi tegner bildene på lerretet, la oss lage fire arrays for å holde posisjonene og størrelsene på knappene (playImage, instructImage, settingsImage, creditsImage). Disse arrays vil bli brukt senere for å opprette en mus over funksjon.

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

Nå kan vi tegne bildene til lerretet; Dette kan gjøres innen en på Last funksjon for hvert bilde, men en onload-funksjon trenger ikke å bli inkludert - vi kan bare bruke drawImage ().

 bgImage.onload = function () context.drawImage (bgImage, 0, 0); ; logoImage.onload = function () context.drawImage (logoImage, 50, -10);  playImage.onload = function () context.drawImage (playImage, buttonX [0], buttonY [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]); 

Hvis testet nå, bør du se et statisk bilde av en meny som vi snart vil puste inn i. Skipet ble ikke trukket inn med resten av bildene fordi vi skal tegne det senere i en mus event. For øvrig, hvis du ikke har gjort dette så langt, hold variablene gruppert sammen øverst og gjør det samme med funksjoner.


Trinn 3: Animere gjennom intervaller

JavaScript mangler en onEnterFrame () ekvivalent, men vi kan enkelt lage vår egen gjennom bruk av et intervall (timer).

 var rammer = 30; var timerId = 0; timerId = setInterval (oppdatering, 1000 / rammer);

Du kan være forvirret på hvordan intervallet virker, så jeg vil forklare det i korte trekk. Intervallet ringer funksjonen Oppdater() hver (1000 /rammer) millisekunder for å opprette en jevn oppdateringsfrekvens. Verdien av rammer kontrollerer fps; hvis rammer er 25 da vil nettleseren forsøke å ringe Oppdater() hver (1000/25 =) 40 millisekunder.

Vår neste åpenbare skritt er å skape funksjonen Oppdater()

 funksjon oppdatering () clear (); bevege seg(); tegne(); 

Tre flere funksjoner ble nettopp kalt. klar() brukes til å rydde lerretet fordi i motsetning til blits fungerer lerretet som å sette klistremerker på et brett; Bildene kan ikke flyttes etter at de er plassert. Den neste funksjonen, bevege seg(), brukes til å endre variabelverdiene som brukes med bildene. Endelig tegne() kalles for å plassere disse "klistremerkene".

 funcion clear () context.clearRect (0, 0, bredde, høyde); 

Enkelt sagt, fjerner denne koden alt innenfor rektangelet som er størrelsen på lerretet og trekkes fra (0,0), øverste venstre hjørne. Det betyr at det rydder hele synlig lerret.

Før vi går videre til neste funksjon, bør to variabler innføres. backgroundY vil være variabelen for bakgrunnsbildets y-posisjon og hastighet vil bli brukt til å trekke fra backgroundY hver oppdateringssyklus.

 var backgroundY = 0; var hastighet = 1;

Effekten som vi skal produsere er en kontinuerlig rullende bakgrunn. Bildet består av to identiske stjernefeltbilder, den ene over den andre, i et større bilde (bildet er dobbelt så høyt som lerretet). Vi vil sakte bevege bildet opp til den andre halvdelen er helt synlig, og da vil vi nullstille posisjonen til bildet tilbake til første halvdel.

 funksjonsflyt () backgroundY - = speed; hvis (backgroundY == -1 * høyde) backgroundY = 0; 

Endelig har vi tegne() funksjon. Alle bildene vil bli revet, men en endring til varsel er at bgImages y-verdi er erstattet med variabelen backgroundY.

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

Test nå og beundre den glatte rullingsbakgrunnen.


Trinn 4: Kontrollerer museposisjonen

En ting HTML5 Mangler er støtte for lyttere av bildehendelse, noe som betyr at vi ikke bare kan skrive playImage.mouseover = funksjon () . I stedet må vi få stillingen av musen i forhold til lerretet og finne ut om det er over et objekt.

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

De to variablene som blir introdusert, skal brukes til å få den nåværende posisjonen til musen. Vi har lagt til en hendelseslytter, som i ActionScript, som kaller funksjonen checkPos () hver gang musen beveger seg.

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

Hvis du varslet verdiene til mouseX og Mousey hver gang du flyttet musen, ville du få riktig posisjon. Men det er ett problem: Ikke alle moderne desktop-nettlesere støtter denne metoden. For å overvinne dette problemet kan vi bruke den lille hacken i stedet:

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

Dette kontrollerer om nettleseren bruker "side" eller "offset" egenskaper for å returnere musens posisjon og justerer verdiene (om nødvendig) for å få museposisjonen i forhold til lerretet.

Husk at skipet vi instanserte, men ikke tegnet? Vi skal ta det statiske bildet, snurre det og få det til å vises når vi musen over knappene!

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

De fire første variablene er de samme som før (vi har to posisjoner fordi det kommer to skip). De shipVisible variabel vil bli satt sant når musen er over en knapp. Som for shipSize og shipRotate, De vil bli brukt til å skalle skipet vertikalt og omplassere det for å gi illusjonen at den spinner. Husk at bildene skaler rett til venstre.

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

Legg til koden i checkPos () funksjon. Først sykler vi gjennom knappene det er (jeg fant ut verdien ved hjelp av buttonX.length). Neste sammenligner vi mouseX for å se om den er større enn gjeldende knapp buttonX og mindre enn sin buttonX + buttonWidth - dvs. innenfor de horisontale grensene til knappen. Vi gjentar prosessen i en annen hvis setning for Y-verdiene. Hvis dette er helt sant, må musen være over en knapp, så sett shipVisible til ekte:

 shipVisible = true;

Og innenfor den tomme ellers uttalelse satt det til falsk; det vil da bli kalt når du musen ut av en knapp:

 shipVisible = false;

Under shipVisible = true vi vil sette innledende verdier for ShipX og shipY, og utfør hele skaleringen i farten og tegne funksjoner.

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

Først og fremst ShipX, som vi bare vil ha til venstre for knappen, setter vi verdien til (nåværende knappens X - halvdel av skipbredden), og jeg flyttet den over 2 piksler til venstre for å få det til å se bedre ut. En lignende prosess gjentas for den første shipY. For den andre ShipX Vi posisjonerer oss på (nåværende knappes X + knapp som er bredde + halve skipbredden), og så stiller vi Y som før.

Den vanskelige delen kommer nå. Vi må skala skipet og flytte det over for å kompensere for skaleringen. Innen bevege seg() funksjon skriv dette hvis uttalelse.

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

Koden begynner å trekke verdien av shipSize, som vil bli brukt til å skalere bildet når vi tegner det Når den når null, går prosessen tilbake til den er full skala igjen.

Nå kan vi flytte inn i tegne() funksjon. Under alle de andre tegne metoder legger du til følgende hvis setning.

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

Skipene trekkes normalt, med unntak av at X-posisjonene kompenseres ved å trekke halvparten av dagens skala.


Trinn 5: Kontrollerer museklikk

Legg til en annen hendelselytter for mouseup og opprett en ny variabel for et annet intervall vi skal lage.

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

Opprett funksjonskontrollKlikk ().

 funksjonskontrollKlikk (mouseEvent) for (i = 0; i < buttonX.length; i++) if(mouseX > buttonX [i] && mouseX < buttonX[i] + buttonWidth[i]) if(mouseY > buttonY [i] && mouseY < buttonY[i] + buttonHeight[i])    

Som før kontrollerer vi om musens posisjon er riktig. Nå må vi opprette det nye intervallet, og stoppe det andre intervallet og hendelseslytterne.

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

Ingenting nytt her bortsett fra at vi trenger å opprette en funksjon som heter fadeout (). Vi må også opprette en annen variabel som heter tid.

 var tid = 0,0;
 funksjon fadeOut () context.fillStyle = "rgba (0,0,0, 0,2)"; context.fillRect (0, 0, bredde, høyde); tid + = 0,1; hvis (tid> = 2) clearInterval (fadeId); tid = 0; timerId = setInterval ("oppdatering ()", 1000 / rammer); canvas.addEventListener ("mousemove", checkPos); canvas.addEventListener ("mouseup", checkClick); 

Den har noen nye metoder, men det er ganske enkelt. Siden vi stoppet alle hendelseslytterne og det andre intervallet, er menyen helt statisk. Så vi trekker gjentatte ganger et gjennomsiktig svart rektangel på toppen av menyen - uten å rydde det - for å gi illusjonen om å falme ut.

Variabelen tid økes hver gang funksjonen kalles og når den når en viss verdi (når 20 "rammer" har gått, i dette tilfellet) fjerner vi gjeldende intervall. Her tilbakestiller jeg menyen, men det er her du vil tegne en ny del av menyen.

En siste ting å merke seg er at når du tegner figurer på lerretet fyllstil er satt med en rgb (rød, grønn, blå) verdi. Når du vil tegne gjennomsiktige former, bruker du rgba (rød, grønn, blå, alfa).

Jeg håper det er demystified litt av læringsprosessen for å bytte fra enkel AS3 programmering til enkel lerret programmering. Legg inn en kommentar hvis du har spørsmål!