HTML5 avoider spillet opplæringen: Multiple Flytte Enemies

HTML5 avoider spillet Tutorial: Flere Moving Enemies
to
Del
3
Del

Dette Cyber ​​Monday Envato Tuts + kurs vil bli redusert til bare $ 3. Ikke gå glipp av.

I første del av denne serien, lært deg det grunnleggende ved hjelp av Javascript og lerretet element for å lage et veldig enkelt HTML5 avoider spillet. Men det er for enkelt - det eneste fiende ikke engang flytte - det er ingen utfordring! I denne opplæringen vil du lære hvordan du oppretter en endeløs strøm av fiender, alt faller fra toppen av skjermen.



Repetisjons

I den første delen av opplæringen vi dekket ganske mange begreper: tegne bilder til skjermen, i samspill mellom HTML og Javascript, oppdager musehandlinger, og hvis setningen. Du kan laste ned kildefilene her hvis du ønsker å dykke inn i denne delen av opplæringen, men jeg anbefaler å lese alle delene i orden.

Vår spillets HTML-siden inneholder et lerret element, noe som utløser en Javascript-funksjon kalt drawAvatar () når det klikkes. At funksjonen er inne i en egen fil som heter main.js, og det gjør to ting:.

  • Tegner en kopi av avatar.png til lerretet

    Setter opp en hendelse lytteren
    å ringe en annen funksjon, kalt redrawAvatar (), når musen beveger seg over lerretet

    redrawAvatar () -funksjonen er også inne main.js.; motsetning drawAvatar () den godtar en parameter Anmeldelser - kalt mouseEvent - som automatisk sendes til den av arrangementet lytteren. Dette mouseEvent inneholder informasjon om musens posisjon. Funksjonen gjør fire ting:.

  • Tømmer lerretet

    Tegner en kopi av avatar.png til lerretet, på musens posisjon

    Tegner en kopi. av enemy.png til lerretet, på et angitt posisjon.

    sjekker for å se om avatar og fienden er nær nok til hverandre for å være overlappende, og viser et varsel () hvis så.

    Alt klart? Hvis ikke, kan du prøve den varme opp utfordringen.



    Warm Up Challenge

    Hvis det har gått en stund siden du lese første del av serien (eller hvis du bare ønsker å sjekke at du forstår hva som skjer), har en gå på disse små øvelser. De er helt valgfritt og separat til selve opplæringen, så anbefaler jeg å jobbe på en kopi av prosjektet snarere enn originalen. Du kan fullføre alle disse øvelsene kun ved hjelp av informasjon fra den første delen av serien.

    Easy

    Husk at drawImage () fungerer som en potet stempel. Bruk den til å lage en ubrutt ring av fiender rundt kanten av lerretet, som dette:

    (Hvis du blir lei av å kopiere og lime alle disse uttalelsene, gjerne gjøre det til en mindre ring - du kan endre størrelsen lerretet, også, hvis du vil.)

    Medium

    Gjør det "du treffer fienden" alert vises når avataren treffer kanten av ringen. (For å teste dette, husk at du kan trykke Enter for å avvise meldingen,. Du trenger ikke å klikke på OK)

    Hard

    At varselet vil komme opp når du prøver å flytte musen fra utenfor lerretet til inni den, noe som er veldig irriterende hvis du allerede har klikket lerretet. Gjør det mulig å flytte inn i lerretet uten å utløse alarmen -. Men en gang inne, gjør varselet vises når avataren berører ringen av fiender



    Gjør Enemy Flytt

    're kommer til å gjøre fienden faller ned fra toppen av skjermen. For nå, vil vi fokusere på å gjøre det flytte snarere enn på å oppdage en kollisjon, så "kommentere ut" linjene i redrawEnemy () som omhandler kollisjoner, som så:
    //if (mouseEvent.offsetX > 220 & & mouseEvent.offsetX < 280 & & mouseEvent.offsetY > 117 & & mouseEvent.offsetY < 180) {//alert ("Du treffer fienden!"); //}

    Husk: to skråstreker fortelle leseren "ignorere alt på denne linjen fra her på". Tidligere brukte vi dette til å lage kommentarer Anmeldelser - små påminnelser om hva enkelte biter av kode gjøre - men her vi bruker det for et annet formål: å stoppe enkelte biter av kode fra å kjøre uten helt å slette dem. Dette gjør det enkelt for oss å sette koden tilbake senere

    I øyeblikket er fienden tegnet på nytt, i samme posisjon, når vi beveger musen.
    GameCanvas.getContext ("2d" ) .drawImage (enemyImage, 250, 150);

    Husker du Math.random () -funksjonen fra den første delen av opplæringen? Den returnerer et tilfeldig tall mellom null og én; multiplisere det med 300 (høyden på lerretet) ville gi oss et tall mellom 0 og 300. Hva skjer hvis vi trekker fienden på et tilfeldig y-posisjon mellom 0 og 300 hver gang musen ble flyttet? La oss prøve det ut; modifisere den linjen som så:.
    gameCanvas.getContext ("2d") drawImage (enemyImage, 250, Math.random () * 300);

    Prøv det ut her

    Det ser ut som! fienden beveger seg tilfeldig opp og ned en viss linje, men bare når musen beveges. Selvfølgelig er det ikke faktisk
    flytte; det er "teleportere" fra en posisjon til den neste, men dette gir en illusjon av bevegelse.

    Vi ville få en bedre illusjon om den bare flyttet i én retning. Vi kan oppnå dette ved å sørge for fiendens y-posisjon bare øker, og aldri avtar

    Tenk deg følgende kode:.
    Funksjon redrawAvatar (mouseEvent) {var Gamecanvas = document.getElementById ("Gamecanvas"); Var avatarImage = new Image (); Var enemyImage = new Image (); Var enemyY = 0; avatarImage.src = "img /avatar.png"; enemyImage.src = "img /enemy.png"; gameCanvas.width = 400; //dette sletter innholdet i lerretet gameCanvas.getContext ("2d") drawImage (avatarImage, mouseEvent.offsetX, mouseEvent.offsetY.); enemyY = enemyY + 1; //øke enemyY variabel ved én piksel. Hvis enemyY er 10, så enemyY + 1 er 11, etc. gameCanvas.getContext ("2d") drawImage (enemyImage, 250, enemyY.); //if (mouseEvent.offsetX > 220 & & mouseEvent.offsetX < 280 & & mouseEvent.offsetY > 117 & & mouseEvent.offsetY < 180) {//alert ("Du treffer fiende!"); //}}

    Se hva jeg gjør? Jeg satt verdien av enemyY til 0 på toppen av funksjonen, så økte den med én piksel før tegning fienden. På denne måten er jeg som mål å gjøre fiendens y-posisjon øke med én piksel hver gang redrawAvatar () kjøres.

    Men det er en feil i min logikk. Linjen Var enemyY = 0; vil tilbakestille enemyY variabel til 0 hver gang redrawAvatar () kjøres, noe som betyr at det vil alltid bli trukket på et y-posisjonen til en (fordi det vil bli økt på linje 12).

    må bare sette den til 0 gang. Hva hvis vi gjør det i drawEnemy ()? Tross alt, er at funksjonen kun kjørt en gang:
    funksjon drawAvatar () {var Gamecanvas = document.getElementById ("Gamecanvas"); Var avatarImage = new Image (); Var enemyY = 0; avatarImage.src = "img /avatar.png"; . gameCanvas.getContext ("2d") drawImage (avatarImage, Math.random () * 100, Math.random () * 100); gameCanvas.addEventListener ("mousemove", redrawAvatar);} funksjon redrawAvatar (mouseEvent) {var Gamecanvas = document.getElementById ("Gamecanvas"); Var avatarImage = new Image (); Var enemyImage = new Image (); avatarImage.src = "img /avatar.png"; enemyImage.src = "img /enemy.png"; gameCanvas.width = 400; //dette sletter innholdet i lerretet gameCanvas.getContext ("2d") drawImage (avatarImage, mouseEvent.offsetX, mouseEvent.offsetY.); enemyY = enemyY + 1; //øke enemyY variabel ved én piksel. Hvis enemyY er 10, så enemyY + 1 er 11, etc. gameCanvas.getContext ("2d") drawImage (enemyImage, 250, enemyY.); //if (mouseEvent.offsetX > 220 & & mouseEvent.offsetX < 280 & & mouseEvent.offsetY > 117 & & mouseEvent.offsetY < 180) {//alert ("Du treffer fiende!"); //}}

    Prøv det ut her!

    Dessverre, dette fungerer ikke i det hele tatt. Problemet ligger i et konsept som heter omfang
    . Hvis du bruke VAR nøkkelord for å definere en variabel innenfor en funksjon, da variabelen vil kun være tilgjengelig innen den funksjonen. Dette betyr at vår redrawAvatar () -funksjonen ikke har tilgang til samme enemyY variabelen som ble definert i drawAvatar ().

    Men hvis vi definerer en variabel utenfor alle funksjoner, det kan nås ved en av dem! Så, prøv dette:
    Var enemyY = 0; funksjon drawAvatar () {var Gamecanvas = document.getElementById ("Gamecanvas"); Var avatarImage = new Image (); avatarImage.src = "img /avatar.png"; . gameCanvas.getContext ("2d") drawImage (avatarImage, Math.random () * 100, Math.random () * 100); gameCanvas.addEventListener ("mousemove", redrawAvatar);} funksjon redrawAvatar (mouseEvent) {var Gamecanvas = document.getElementById ("Gamecanvas"); Var avatarImage = new Image (); Var enemyImage = new Image (); avatarImage.src = "img /avatar.png"; enemyImage.src = "img /enemy.png"; gameCanvas.width = 400; //dette sletter innholdet i lerretet gameCanvas.getContext ("2d") drawImage (avatarImage, mouseEvent.offsetX, mouseEvent.offsetY.); enemyY = enemyY + 1; //øke enemyY variabel ved én piksel. Hvis enemyY er 10, så enemyY + 1 er 11, etc. gameCanvas.getContext ("2d") drawImage (enemyImage, 250, enemyY.); //if (mouseEvent.offsetX > 220 & & mouseEvent.offsetX < 280 & & mouseEvent.offsetY > 117 & & mouseEvent.offsetY < 180) {//alert ("Du treffer fiende!"); //}}

    Prøv det ut her

    Det fungerer - fienden glir nedover skjermen. Men det gjør bare så mens vi beveger musen. Det er et interessant spillmekanikk, men det er ikke det jeg siktet til.



    Gjør Enemy Move på egne

    Det ville være mye bedre hvis fienden så ut til å bevege seg over seg selv - som betyr, den beveger seg uavhengig av om spilleren beveger musen. Vi kan gjøre dette ved å utløse sin bevegelse (sin "teleportations") basert på tid i stedet for på musen bevegelse.

    Vi kan gjøre dette ved hjelp av setInterval () -funksjonen. Det fungerer slik:
    setInterval (function, periode);

    Her er function navnet på en funksjon vi ønsker å kjøre igjen og igjen, og perioden er tiden (i millisekunder) vi ønsker å passere mellom hver samtale til at funksjonen

    La oss se hvordan dette ser ut.
    Var enemyY = 0; funksjon drawAvatar () {var Gamecanvas = document.getElementById ("Gamecanvas"); Var avatarImage = new Image (); avatarImage.src = "img /avatar.png"; . gameCanvas.getContext ("2d") drawImage (avatarImage, Math.random () * 100, Math.random () * 100); gameCanvas.addEventListener ("mousemove", redrawAvatar); setInterval (redrawEnemy, 1000);} funksjon redrawAvatar (mouseEvent) {var Gamecanvas = document.getElementById ("Gamecanvas"); Var avatarImage = new Image (); avatarImage.src = "img /avatar.png"; gameCanvas.width = 400; //dette sletter innholdet i lerretet gameCanvas.getContext ("2d") drawImage (avatarImage, mouseEvent.offsetX, mouseEvent.offsetY.); //if (mouseEvent.offsetX > 220 & & mouseEvent.offsetX < 280 & & mouseEvent.offsetY > 117 & & mouseEvent.offsetY < 180) {//alert ("Du treffer fiende!"); //}} funksjon redrawEnemy () {var enemyImage = new Image (); enemyImage.src = "img /enemy.png"; enemyY = enemyY + 1; //øke enemyY variabel ved én piksel. Hvis enemyY er 10, så enemyY + 1 er 11, etc. gameCanvas.getContext ("2d") drawImage (enemyImage, 250, enemyY);.}

    Jeg har flyttet all koden som omhandler flytting og tegning fiende til den nye redrawEnemy () -funksjonen, og jeg har satt den til å bli kalt 1000 millisekunder (hvert sekund) med en setInterval () kall i drawAvatar (). (I motsetning til når du bruker en hendelse lytteren, ingen parametere automatisk bli overført til redrawEnemy () når vi kaller det fra setInterval ().)

    Prøv det ut her! . Klikk på lerretet, så ikke flytte musen

    Det er et par ting som er galt med dette:

    Fienden later en sti - dette er fordi lerretet er ikke ryddet i redrawEnemy ()

    De fiendens bevegelser virkelig sakte -. kanskje 1000 millisekunder er for lenge å vente

    Når avataren er flyttet, forsvinner fienden -. Dette er fordi fienden er bare trukket i redrawEnemy (); i redrawAvatar () lerretet er ryddet og avataren er tegnet på nytt, men ikke fienden.

    La oss løse disse en om gangen. Først vil vi fjerne lerretet i redrawEnemy ():
    funksjon redrawEnemy () {var enemyImage = new Image (); enemyImage.src = "img /enemy.png"; gameCanvas.width = 400; //dette sletter innholdet i lerretet enemyY = enemyY + 1; //øke enemyY variabel ved én piksel. Hvis enemyY er 10, så enemyY + 1 er 11, etc. gameCanvas.getContext ("2d") drawImage (enemyImage, 250, enemyY);.!}

    Prøv det ut her

    Hm. Nå avataren forsvinner når fienden er trukket, og vice-versa. Selvfølgelig, dette er fornuftig; vi tømme lerretet i både redrawEnemy () og redrawAvatar (), men aldri trekke både fienden og avataren samtidig.

    Hva om vi flyttet
    fienden i redrawEnemy () - ved å øke verdien av enemyY - men faktisk trakk
    det i redrawAvatar ()
    Var enemyY = 0;? funksjon drawAvatar () {var Gamecanvas = document.getElementById ("Gamecanvas"); Var avatarImage = new Image (); avatarImage.src = "img /avatar.png"; . gameCanvas.getContext ("2d") drawImage (avatarImage, Math.random () * 100, Math.random () * 100); gameCanvas.addEventListener ("mousemove", redrawAvatar); setInterval (redrawEnemy, 1000);} funksjon redrawAvatar (mouseEvent) {var Gamecanvas = document.getElementById ("Gamecanvas"); Var avatarImage = new Image (); Var enemyImage = new Image (); enemyImage.src = "img /enemy.png"; avatarImage.src = "img /avatar.png"; gameCanvas.width = 400; //dette sletter innholdet i lerretet gameCanvas.getContext ("2d") drawImage (avatarImage, mouseEvent.offsetX, mouseEvent.offsetY.); gameCanvas.getContext ("2D") drawImage (enemyImage, 250, enemyY.); //if (mouseEvent.offsetX > 220 & & mouseEvent.offsetX < 280 & & mouseEvent.offsetY > 117 & & mouseEvent.offsetY < 180) {//alert ("Du treffer fiende!"); //}} funksjon redrawEnemy () {enemyY = enemyY + 1; //øke enemyY variabel ved én piksel. Hvis enemyY er 10, så enemyY + 1 er 11, osv.}

    Prøv det ut her!

    Den slags jobber, men vi er tilbake til det problemet der fienden bare beveger seg mens du ' re bevege musen. Men denne gangen er det litt annerledes; for å gjøre dette mer åpenbare, kan vi øke fiendens hastigheten ved å redusere perioden. Sett den til 25 (som er 1 /40th av et sekund, noe som betyr redrawEnemy () kjøres 40 ganger per sekund):
    setInterval (redrawEnemy, 25);

    Prøv det ut her

    Sammenlign dette med den tidligere versjonen hvor fienden bare flyttes når musa var i bevegelse. Se forskjellen? I den nye, holder fiendens posisjon i endring, men det gjør det "bak kulissene"; selve bilde
    av fienden bare beveger seg når musen beveges. Hvis du venter et sekund eller så før du flytter musen, hopper fienden bildet ned på skjermen for å ta opp kontakten med sin faktiske posisjon.

    Skille fiendens faktiske
    posisjon fra fiendens bildes
    posisjon som dette kommer til å la oss løse vårt problem.

    Før vi går videre, er du får forvirret av funksjonsnavnene? Jeg er. redrawEnemy () er faktisk ikke trekke fienden i det hele tatt. La oss gi dem nytt navn til noe litt lettere å holde styr på.

  • drawAvatar () kjøres når vi starter spillet, og det setter alt opp, så la oss endre navnet til setUpGame () Anmeldelser
    redrawAvatar () kjøres når musen beveger seg, så la oss endre navnet til handleMouseMovement ()

    redrawEnemy () kjøres hver brøkdel av et sekund; det er som om det er en klokke som tikker 40 ganger i sekundet, og hvert tick utløser funksjonen. Så, la oss endre navnet til handleTick ()

    Ikke glem at du må endre navn på alle de referanser
    til funksjonene også, i tilfelle lytteren og setInterval (). Her er hva det vil se ut:
    Var enemyY = 0; funksjon setUpGame () {var Gamecanvas = document.getElementById ("Gamecanvas"); Var avatarImage = new Image (); avatarImage.src = "img /avatar.png"; . gameCanvas.getContext ("2d") drawImage (avatarImage, Math.random () * 100, Math.random () * 100); gameCanvas.addEventListener ("mousemove", handleMouseMovement); setInterval (handleTick, 25);} funksjon handleMouseMovement (mouseEvent) {var Gamecanvas = document.getElementById ("Gamecanvas"); Var avatarImage = new Image (); Var enemyImage = new Image (); enemyImage.src = "img /enemy.png"; avatarImage.src = "img /avatar.png"; gameCanvas.width = 400; //dette sletter innholdet i lerretet gameCanvas.getContext ("2d") drawImage (avatarImage, mouseEvent.offsetX, mouseEvent.offsetY.); gameCanvas.getContext ("2D") drawImage (enemyImage, 250, enemyY.); //if (mouseEvent.offsetX > 220 & & mouseEvent.offsetX < 280 & & mouseEvent.offsetY > 117 & & mouseEvent.offsetY < 180) {//alert ("Du treffer fiende!"); //}} funksjon handleTick () {enemyY = enemyY + 1; //øke enemyY variabel ved én piksel. Hvis enemyY er 10, så enemyY + 1 er 11, etc}

    (Du trenger også å endre HTML-side, slik at lerretet er onclick attributt er. "SetUpGame ();" heller enn "drawAvatar (); . "

    Jeg tror dette gjør det lettere å se hva som skjer:

    Når musen beveger seg, beveger vi oss avataren sin stilling, trekke avatar i sin nåværende stilling, og trekke fienden i sin nåværende stilling.

    Når klokken tikker, beveger vi oss fiendens posisjon.

    Vi trenger å trekke fienden og avataren samtidig (dvs. i samme funksjon) ..

    Hvis vi bare trekke fienden når musen beveger seg, så fiendens bevegelser er ikke jevne

    Dette gjør det enklere i sin tur for å se en mulig løsning:


    Når musen beveger seg, flytter avatar posisjon.

    Når klokken tikker, flytte fiendens posisjon, trekke avatar i sin nåværende stilling, og trekke fienden i sin nåværende stilling. < .no>

    La oss gjennomføre det. Alt vi trenger å gjøre er å flytte grafikk koden fra handleMouseMovement () for å handleTick (), ikke sant? Liker du dette:
    Var enemyY = 0; funksjon setUpGame () {var Gamecanvas = document.getElementById ("Gamecanvas"); Var avatarImage = new Image (); avatarImage.src = "img /avatar.png"; . gameCanvas.getContext ("2d") drawImage (avatarImage, Math.random () * 100, Math.random () * 100); gameCanvas.addEventListener ("mousemove", handleMouseMovement); setInterval (handleTick, 25);} funksjon handleMouseMovement (mouseEvent) {//if (mouseEvent.offsetX > 220 & & mouseEvent.offsetX < 280 & & mouseEvent.offsetY > 117 & & mouseEvent. offsetY < 180) {//alert ("Du treffer fienden!"); //}} funksjon handleTick () {var avatarImage = new Image (); Var enemyImage = new Image (); enemyY = enemyY + 1; //øke enemyY variabel ved én piksel. Hvis enemyY er 10, så enemyY + 1 er 11, etc. enemyImage.src = "img /enemy.png"; avatarImage.src = "img /avatar.png"; gameCanvas.width = 400; //dette sletter innholdet i lerretet gameCanvas.getContext ("2d") drawImage (avatarImage, mouseEvent.offsetX, mouseEvent.offsetY.); gameCanvas.getContext ("2D") drawImage (enemyImage, 250, enemyY.); }

    Hmm. Det er ikke riktig. Vi har ingenting igjen i handleMouseMovement (). Ah - men det er fordi vi ikke har skilt avataren image posisjon fra avataren faktiske posisjon, som vi gjorde med fienden. Så la oss gjøre det:
    Var enemyY = 0; Var avatarX = 0; Var avatarY = 0; funksjon setUpGame () {var Gamecanvas = document.getElementById ("Gamecanvas"); Var avatarImage = new Image (); avatarImage.src = "img /avatar.png"; . gameCanvas.getContext ("2d") drawImage (avatarImage, Math.random () * 100, Math.random () * 100); gameCanvas.addEventListener ("mousemove", handleMouseMovement); setInterval (handleTick, 25);} funksjon handleMouseMovement (mouseEvent) {avatarX = mouseEvent.offsetX; avatarY = mouseEvent.offsetY; //if (mouseEvent.offsetX > 220 & & mouseEvent.offsetX < 280 & & mouseEvent.offsetY > 117 & & mouseEvent.offsetY < 180) {//alert ("Du treffer fiende!"); //}} funksjon handleTick () {var Gamecanvas = document.getElementById ("Gamecanvas"); Var avatarImage = new Image (); Var enemyImage = new Image (); enemyY = enemyY + 1; //øke enemyY variabel ved én piksel. Hvis enemyY er 10, så enemyY + 1 er 11, etc. enemyImage.src = "img /enemy.png"; avatarImage.src = "img /avatar.png"; gameCanvas.width = 400; //dette sletter innholdet i lerretet gameCanvas.getContext ("2d") drawImage (avatarImage, avatarX, avatarY.); gameCanvas.getContext ("2D") drawImage (enemyImage, 250, enemyY.); }

    Vi må lage nye variabler til å lagre avataren faktiske x- og y-posisjoner, og definere disse variablene utenom noen funksjon, slik at vi kan få tilgang til dem fra hvor som helst.

    Prøv det ut her !

    Dette fungerer! (Hvis det er litt hakkete, og deretter prøve å lukke noen faner eller starte Chrome, som fungerte for meg.) Vi har nå et bevegelig fiende. Tok en stund å komme dit, men selve koden vi har endt opp med er ikke så komplisert, håper jeg du er enig.

    Hvis du vil ha en utfordring, kan du prøve å gjeninnføre den dueller varsling eske. Ikke bekymre deg hvis du har problemer; Vi vil gå gjennom dette igjen litt senere.

    I mellomtiden vil vi se på et problem du sannsynligvis ikke har kommet over ennå ...



    Laster Bildene fra en server

    Som jeg nevnte i den første delen av denne serien, hvis du setter ditt spill på en webserver som det er nå, vil det ikke fungere på riktig måte, selv om de fungerer fint når du kjører fra datamaskinen. Mine demoer jobbe fordi jeg har gjort en liten endring til koden; her er hvordan spillet kjører uten at kode:

    Prøv det ut her

    Hva er det som skjer.? Vel, det er å gjøre med bildene. Hver gang klokken tikker, skaper vi et nytt bilde og sette sin kilde til å peke på en selve bildefilen. Dette fører ikke til problemer når bildefilen er på harddisken, men når det er på internett, siden kan prøve å laste ned bildet før tegne den -. Fører til flimring som vi kan se i demoen

    Kanskje kan du allerede gjette på en løsning, basert på hva vi har gjort i denne opplæringen så langt. Akkurat som med fienden og avatar posisjoner, kan vi gå fiendens og avatarens bilder utenfor funksjonene, og bruke dem om igjen og om igjen, uten å definere dem og sette sine verdier i handleTick () fungere hver gang.

    Ta en titt:
    Var enemyY = 0; Var avatarX = 0; Var avatarY = 0; Var avatarImage; Var enemyImage; funksjon setUpGame () {var Gamecanvas = document.getElementById ("Gamecanvas"); avatarImage = new Image (); enemyImage = new Image (); enemyImage.src = "img /enemy.png"; avatarImage.src = "img /avatar.png"; . gameCanvas.getContext ("2d") drawImage (avatarImage, Math.random () * 100, Math.random () * 100); gameCanvas.addEventListener ("mousemove", handleMouseMovement); setInterval (handleTick, 25);} funksjon handleMouseMovement (mouseEvent) {avatarX = mouseEvent.offsetX; avatarY = mouseEvent.offsetY; //if (mouseEvent.offsetX > 220 & & mouseEvent.offsetX < 280 & & mouseEvent.offsetY > 117 & & mouseEvent.offsetY < 180) {//alert ("Du treffer fiende!"); //}} funksjon handleTick () {var Gamecanvas = document.getElementById ("Gamecanvas"); enemyY = enemyY + 1; //øke enemyY variabel ved én piksel. Hvis enemyY er 10, så enemyY + 1 er 11, etc. gameCanvas.width = 400; //dette sletter innholdet i lerretet gameCanvas.getContext ("2d") drawImage (avatarImage, avatarX, avatarY.); gameCanvas.getContext ("2D") drawImage (enemyImage, 250, enemyY.); }

    Prøv det ut her - uten flimring

    I tilfelle du lurer: vi kunne ha flyttet linjene 9-12 utsiden av funksjonene også!. Jeg valgte å sette dem i setUpGame () rett og slett fordi de syntes å være mer om, vel, sette opp spillet.



    Gjør annen Enemy

    Det er faktisk veldig enkelt å lage en ny fiende vises på skjermen. Husk at bilder er som potet frimerker; det betyr at det er ingenting som hindrer oss fra å tegne fienden bildet på lerretet i to forskjellige steder i samme tick:
    funksjon handleTick () {var Gamecanvas = document.getElementById ("Gamecanvas"); enemyY = enemyY + 1; //øke enemyY variabel ved én piksel. Hvis enemyY er 10, så enemyY + 1 er 11, etc. gameCanvas.width = 400; //dette sletter innholdet i lerretet gameCanvas.getContext ("2d") drawImage (avatarImage, avatarX, avatarY.); gameCanvas.getContext ("2D") drawImage (enemyImage, 250, enemyY.); . gameCanvas.getContext ("2d") drawImage (enemyImage, 100, enemyY);}
    Klikk for å prøve det ut

    Enkelt

    Du kan sette dem i ulike høyder, slik:.!
    funksjon handleTick () {var Gamecanvas = document.getElementById ("Gamecanvas"); enemyY = enemyY + 1; //øke enemyY variabel ved én piksel. Hvis enemyY er 10, så enemyY + 1 er 11, etc. gameCanvas.width = 400; //dette sletter innholdet i lerretet gameCanvas.getContext ("2d") drawImage (avatarImage, avatarX, avatarY.); gameCanvas.getContext ("2D") drawImage (enemyImage, 250, enemyY.); . gameCanvas.getContext ("2d") drawImage (enemyImage, 100, enemyY - 50);}
    Klikk for å prøve det ut

    Dette er litt rotete, men.. I stedet, hva med bare å skape en enemyY2 variabel
    Var enemyY = 0;? Var enemyY2 = -50; Var avatarX = 0; Var avatarY = 0; Var avatarImage; Var enemyImage; //... funksjon handleTick () { Var Gamecanvas = document.getElementById ("Gamecanvas"); enemyY = enemyY + 1; //øke enemyY variabel ved én piksel. Hvis enemyY er 10, så enemyY + 1 er 11, etc. enemyY2 = enemyY2 + 1; gameCanvas.width = 400; //dette sletter innholdet i lerretet gameCanvas.getContext ("2d") drawImage (avatarImage, avatarX, avatarY.); gameCanvas.getContext ("2D") drawImage (enemyImage, 250, enemyY.); gameCanvas.getContext ("2d") drawImage (enemyImage, 100, enemyY2);..}

    Nå kan du sette de første posisjonene enemyY og enemyY2 til hva du vil, uten å måtte endre koden i handleTick ()



    Gjør Fem Enemies

    Prøv å utvide det vi nettopp har gjort, slik at det er fem fiender, alle med forskjellig utgangspunkt. Ta en titt på min kode hvis du må. Her er et hint: du trenger bare å legge kode utenfor funksjoner og inne i handleTick () funksjon - du trenger ikke å røre setUpGame () eller handleMouseMovement ()
    Var enemyY = 0; Var enemyY2 = -50; Var enemyY3. = -75; Var enemyY4 = -120; Var enemyY5 = -250; Var avatarX = 0; Var avatarY = 0; Var avatarImage; Var enemyImage; //... funksjon handleTick () {var Gamecanvas = document.getElementById (" Gamecanvas "); enemyY = enemyY + 1; //øke enemyY variabel ved én piksel. Hvis enemyY er 10, så enemyY + 1 er 11, etc. enemyY2 = enemyY2 + 1; enemyY3 = enemyY3 + 1; enemyY4 = enemyY4 + 1; enemyY5 = enemyY5 + 1; gameCanvas.width = 400; //dette sletter innholdet i lerretet gameCanvas.getContext ("2d") drawImage (avatarImage, avatarX, avatarY.); gameCanvas.getContext ("2D") drawImage (enemyImage, 250, enemyY.); gameCanvas.getContext ("2D") drawImage (enemyImage, 130, enemyY2.); gameCanvas.getContext ("2D") drawImage (enemyImage, 300, enemyY3.); gameCanvas.getContext ("2d") drawImage (enemyImage, 50, enemyY4.); gameCanvas.getContext ("2d") drawImage (enemyImage, 190, enemyY5);..}
    Klikk for å prøve det ut



    Gjør Ti Enemies

    Å, dette kommer til å få kjedelig, ikke sant? Opprettholde alle de fiender, og legge til tre linjer med kode for hver enkelt. Yuck.

    Tillat meg å presentere arrays
    . Ta en titt på denne:
    Var enemyYPositions = [0, -50, -75, -120, -250]; Var avatarX = 0; Var avatarY = 0; Var avatarImage; Var enemyImage; //... funksjon handleTick () {var Gamecanvas = document.getElementById ("Gamecanvas"); enemyYPositions [0] = enemyYPositions [0] + 1; enemyYPositions [1] = enemyYPositions [1] + 1; enemyYPositions [2] = enemyYPositions [2] + 1; enemyYPositions [3] = enemyYPositions [3] + 1; enemyYPositions [4] = enemyYPositions [4] + 1; gameCanvas.width = 400; //dette sletter innholdet i lerretet gameCanvas.getContext ("2d") drawImage (avatarImage, avatarX, avatarY.); gameCanvas.getContext ("2d") drawImage (enemyImage, 250, enemyYPositions [0]).; gameCanvas.getContext ("2D") drawImage (enemyImage, 130, enemyYPositions [1].); gameCanvas.getContext ("2d") drawImage (enemyImage, 300, enemyYPositions [2].); gameCanvas.getContext ("2D") drawImage (enemyImage, 50, enemyYPositions [3]).; gameCanvas.getContext ("2d") drawImage (enemyImage, 190, enemyYPositions [4]);}

    Dette gir oss nøyaktig samme resultat som før, men:.

    Alle fiender 'y stillinger er definert i en enkelt linje, og Selge
    Vi får en enkel måte å referere til noen av disse stillingene. enemyYPosition [enemyNumber]

    Denne type variabel kalles en rekke
    ; det er en måte å holde en liste over verdier (eller av andre variabler), og lar oss hente noen elementer fra den listen ved hjelp av et nummer. Legg merke til at det første elementet i en matrise er tallet 0, er den andre verdien nummer 1, og så videre - vi kaller arrays "null-basert" på grunn av dette

    Looping

    Nå tar. en titt på denne delen av koden:
    enemyYPositions [0] = enemyYPositions [0] + 1; enemyYPositions [1] = enemyYPositions [1] + 1; enemyYPositions [2] = enemyYPositions [2] + 1; enemyYPositions [3] = enemyYPositions [3] + 1; enemyYPositions [4] = enemyYPositions [4] + 1;

    Vi gjør det samme, om og om igjen, til ulike elementer i tabellen. Hver kodelinje er den samme som alle de andre, med unntagelse av at antallet inne i hakeparentes endringer. Dette er flott, fordi vi kan skrive kode for å si "gjøre dette samme fem ganger, men å endre ett tall hver gang". For eksempel:
    Var currentNumber = 0; while (currentNumber < 5) {alert (currentNumber); currentNumber = currentNumber + 1;}

    Hvis du setter dette i din JS-fil (i setUpGame (), for eksempel), ville det gjøre siden skjermen fem varsel bokser: det første ville si "0"; den andre vil si "1"; og så videre opp til "4". Med andre ord, det tilsvarer å gjøre dette:
    Var currentNumber = 0; alert (currentNumber); currentNumber = currentNumber + 1; alert (currentNumber); currentNumber = currentNumber + 1; alert (currentNumber); currentNumber = currentNumber + 1; alert (currentNumber); currentNumber = currentNumber + 1; alert (currentNumber); currentNumber = currentNumber + 1;

    Dette er fordi mens Ofte fungerer som en gjentatt hvis setningen. Husk, hvis verk som dette:
    if (betingelse) {utfall;}

    "Hvis betingelsen er sann, og deretter kjøre utfall."

    mens verk som dette:
    while (tilstand) {utfall;}

    ". Så lenge tilstanden er fortsatt til stede, holde kjører utfallet"

    Det er en subtil forskjell, men en veldig viktig en. En hvis blokk vil kjøre bare én gang, hvis betingelsen er sann; en stund blokk vil kjøre om og om igjen før tilstanden stopper tilstand slutter å være sant

    På grunn av dette utfallet -. koden som kjøres inne i mens blokken - vanligvis inneholder noen kode som vil, til slutt, årsaken betingelse for å slutte å være sant; hvis det gjorde ikke koden vil bare gjenta seg alltid. I vårt varslingsboks eksempel økte vi verdien av currentNumber før det "currentNumber" var ikke lenger sant (når currentNumber nådd 5, var det ikke lenger mindre enn
    5, som er grunnen til at vi aldri se en varselboks som inneholder tallet 5).

    Running kode om og om igjen på denne måten kalles "looping", og mens blokken kalles en "loop". La oss nå ta denne koden:
    enemyYPositions [0] = enemyYPositions [0] + 1; enemyYPositions [1] = enemyYPositions [1] + 1; enemyYPositions [2] = enemyYPositions [2] + 1;