Leer CreateJS door een HTML5 Pong-spel te bouwen

Het web beweegt snel - zo snel dat onze originele EaselJS-tutorial al verouderd is! In deze zelfstudie leert u hoe u de nieuwste CreateJS-suite kunt gebruiken door een eenvoudige Pong-kloon te maken.


Eindresultaat voorbeeld

Laten we eens kijken naar het eindresultaat waar we naartoe zullen werken:

Klik om te spelen

Deze tutorial is gebaseerd op het Create a Pong-spel van Carlos Yanez in HTML5 met EaselJS, dat op zijn beurt voortbouwde op zijn handleiding Getting Started With EaselJS. De grafische en geluidseffecten zijn allemaal afkomstig uit de vorige zelfstudie.


Stap 1: Maken index.html

Dit zal ons belangrijkste zijn index.html het dossier:

    pong             

Zoals je ziet is het vrij kort en bestaat het voornamelijk uit het laden van de CreateJS-bibliotheken.

Sinds de release van CreateJS (die in feite alle afzonderlijke EaselJS-bibliotheken bundelt) hoeven we niet langer de JS-bestanden te downloaden en te hosten op onze website; de bestanden worden nu in een CDN (Content Delivery Network) geplaatst, waardoor we deze bestanden zo snel mogelijk op afstand kunnen laden.

Laten we de code herzien:

 

Deze regel verwijdert de mobiele markering die kan worden weergegeven wanneer u de game probeert te spelen op mobiele apparaten. (De mobiele markering zorgt ervoor dat het canvasobject wordt gemarkeerd en negeert zo uw vingerbewegingen.)

Vervolgens hebben we het laden van de CreateJS-bibliotheken:>

     

Deze code laadt de JS-bestanden van de CreateJS CDN en het stelt ons in principe in staat om elk van de CreateJS-functies in onze code te gebruiken

Vervolgens laden we de SoundJS Flash-plug-in, die geluidsbesturing biedt voor browsers die HTML5 Audio niet ondersteunen. Dit wordt gedaan door een SWF (een Flash-object) te gebruiken om de geluiden te laden.

 

In dit geval zullen we het CDN niet gebruiken; in plaats daarvan zullen we de SoundJS-bibliotheek downloaden van http://createjs.com/#!/SoundJS/download en de soundjs.flashplugin-0.2.0.min.js en FlashAudioPlugin.swf bestanden in een lokale map met de naam middelen.

Als laatste van de JS-bestanden laden we de main.js bestand dat alle code bevat voor onze game:

 

Laten we ten slotte een Canvas-object op ons podium plaatsen.

   

Nu kunnen we aan de spelcode gaan werken.


Stap 2: De variabelen

Onze spelcode bevindt zich in een bestand met de naam main.js, dus maak en sla dit nu op.

Laten we allereerst de variabelen definiëren voor alle grafische objecten in het spel:

 var canvas; // Wordt gekoppeld aan het canvas in onze index.html pagina var stage; // Is het equivalent van fase in AS3; we zullen er "kinderen" aan toevoegen // Afbeeldingen // [Achtergrond] var bg; // De achtergrondafbeelding // [Titelweergave] var main; // De hoofdachtergrond var startB; // De Start-knop in het hoofdmenu var creditsB; // De credits-knop in het hoofdmenu // [Credits] var credits; // Het scherm Credits // [Game View] var player; // De speler paddle grafische var bal; // De grafische bal var cpu; // De CPU paddle var wint; // De winnende popup var verliest; // De verliezende popup

Ik heb een opmerking voor elke variabele toegevoegd, zodat u weet wat we in die variabele zullen laden

Vervolgens de scores:

 // [Score] var playerScore; // De hoofdspeler scoort var cpuScore; // De CPU-score var cpuSpeed ​​= 6; // De snelheid van de CPU-paddle; hoe sneller hoe moeilijker het spel is

We hebben variabelen nodig voor de snelheid van de bal:

 // Variabelen var xSpeed ​​= 5; var ySpeed ​​= 5;

U kunt deze waarden wijzigen in wat u maar wilt, als u het spel gemakkelijker of moeilijker wilt maken.

Als je een Flash-ontwikkelaar bent, weet je dat Flash's onEnterFrame is erg handig bij het maken van games, omdat er dingen zijn die in elk frame moeten gebeuren. (Als je niet bekend bent met dit idee, lees dan dit artikel over de Game Loop.)

We hebben een equivalent voor onEnterFrame in CreateJS, en dat is het ticker object, dat elke fractie van een seconde code kan uitvoeren. Laten we de variabele maken die ernaar linkt:

 var tkr = new Object;

Vervolgens hebben we de preloader, die de nieuwe PreloadJS-methoden zal gebruiken.

 // preloader var preloader; var manifest; var totalLoaded = 0;
  • preloader - bevat het PreloadJS-object.
  • manifesteren - zal de lijst met bestanden bevatten die we moeten laden.
  • totalLoaded - deze variabele bevat het aantal reeds geladen bestanden.

Last but not least in onze lijst van variabelen, hebben we TitleView, waarin verschillende afbeeldingen kunnen worden bewaard om ze samen weer te geven (zoals een flitser) DisplayObjectContainer).

 var TitleView = nieuwe container ();

Laten we verder gaan met de hoofdfunctie ...


Stap 3: De hoofdfunctie ()

Deze functie is de eerste functie die wordt uitgevoerd na alle JS-bestanden van de index.html zijn geladen. Maar wat noemt deze functie?

Nou, onthoud deze regel van de index.html het dossier?

 

Dit codefragment geeft aan dat zodra de HTML- (en JS-bibliotheken) zijn geladen, de Hoofd functie zou moeten lopen.

Laten we het eens bekijken:

 function Main () / * Link Canvas * / canvas = document.getElementById ('PongStage'); stage = nieuwe Stage (canvas); stage.mouseEventsEnabled = true; / * Stel de Flash-plug-in in voor browsers die SoundJS * / SoundJS.FlashPlugin niet ondersteunen.BASE_PATH = "assets /"; if (! SoundJS.checkPlugin (true)) alert ("Fout!"); terug te keren;  manifest = [src: "bg.png", id: "bg", src: "main.png", id: "main", src: "startB.png", id: "startB" , src: "creditsB.png", id: "creditsB", src: "credits.png", id: "credits", src: "paddle.png", id: "cpu", src: "paddle.png", id: "player", src: "ball.png", id: "ball", src: "win.png", id: "win", src : "lose.png", id: "lose", src: "playerScore.mp3 | playerScore.ogg", id: "playerScore", src: "enemyScore.mp3 | enemyScore.ogg", id: " enemyScore ", src:" hit.mp3 | hit.ogg ", id:" hit ", src:" wall.mp3 | wall.ogg ", id:" wall "]; preloader = new PreloadJS (); preloader.installPlugin (SoundJS); preloader.onProgress = handleProgress; preloader.onComplete = handleComplete; preloader.onFileLoad = handleFileLoad; preloader.loadManifest (manifest); / * Ticker * / Ticker.setFPS (30); Ticker.addListener (trap); 

Laten we elk onderdeel afbreken:

 canvas = document.getElementById ('PongStage'); stage = nieuwe Stage (canvas); stage.mouseEventsEnabled = true;

Hier koppelen we de PongStage Canvas object uit de index.html bestand naar de canvas-variabele en maak vervolgens een Stage-object van dat canvas. (Op het podium kunnen we objecten plaatsen.)

mouseEventsEnabled stelt ons in staat om muisgebeurtenissen te gebruiken, zodat we muisbewegingen en klikken kunnen detecteren.

 / * Stel de Flash-plug-in in voor browsers die SoundJS * / SoundJS.FlashPlugin niet ondersteunen.BASE_PATH = "assets /"; if (! SoundJS.checkPlugin (true)) alert ("Fout!"); terug te keren; 

Hier configureren we waar de Flash-geluidsplug-in zich bevindt voor die browsers waarin HTML5 Audio niet wordt ondersteund

 manifest = [src: "bg.png", id: "bg", src: "main.png", id: "main", src: "startB.png", id: "startB" , src: "creditsB.png", id: "creditsB", src: "credits.png", id: "credits", src: "paddle.png", id: "cpu",  src: "paddle.png", id: "player", src: "ball.png", id: "ball", src: "win.png", id: "win", src: "lose.png", id: "lose", src: "playerScore.mp3 | playerScore.ogg", id: "playerScore", src: "enemyScore.mp3 | enemyScore.ogg", id: "enemyScore ", src:" hit.mp3 | hit.ogg ", id:" hit ", src:" wall.mp3 | wall.ogg ", id:" wall "];

In de manifestvariabele plaatsen we een array van bestanden die we willen laden (en voorzien van een unieke ID voor elke variabele). Elk geluid heeft twee formaten - MP3 en OGG - omdat verschillende browsers (in) compatibel zijn met verschillende formaten.

 preloader = new PreloadJS (); preloader.installPlugin (SoundJS); preloader.onProgress = handleProgress; preloader.onComplete = handleComplete; preloader.onFileLoad = handleFileLoad; preloader.loadManifest (manifest);

Hier configureren we het preloader-object met PreloadJS. PreloadJS is een nieuwe toevoeging aan de CreateJS-bibliotheken en best handig.

We maken een nieuw PreloadJS-object en plaatsen dit in de preloader variabele, wijs dan een methode toe aan elke gebeurtenis (onProgress, onComplete, onFileLoad). Eindelijk gebruiken we de preloader om het manifest te laden dat we eerder hebben gemaakt.

 Ticker.setFPS (30); Ticker.addListener (trap);

Hier voegen we het Ticker-object toe aan het werkgebied en stellen we de framesnelheid in op 30 FPS; we zullen het later in de game gebruiken voor de enterFrame functionaliteit.


Stap 4: De Preloader-functies maken

 function handleProgress (event) // use event.loaded om het percentage van de loading -functie handleComplete (event) // getriggerd te krijgen wanneer alle laden is voltooid function handleFileLoad (event) // geactiveerd wanneer een individueel bestand is geladen switch (event.type) case PreloadJS.IMAGE: // afbeelding geladen var img = nieuw afbeelding (); img.src = event.src; img.onload = handleLoadComplete; window [event.id] = nieuwe Bitmap (img); breken; case PreloadJS.SOUND: // geluid geladen handleLoadComplete (); breken; 

Laten we de functies herzien:

  • handleProgress - In deze functie kun je het percentage van de voortgang van het laden volgen met deze parameter: event.loaded. U kunt dit gebruiken om bijvoorbeeld een voortgangsbalk te maken.
  • handleComplete - Deze functie wordt genoemd als alle bestanden zijn geladen (voor het geval u daar iets wilt plaatsen).
  • handleFileLoad - Omdat we twee soorten bestanden laden - afbeeldingen en geluiden - hebben we deze functie die elk bestand apart behandelt. Als het een afbeelding is, maken we een bitmapafbeelding en plaatsen deze in een variabele (waarvan de naam gelijk is aan de ID van de geladen afbeelding) en vervolgens de handleLoadComplete functie (die we hierna zullen schrijven); als het een geluid is, dan bellen we gewoon de handleLoadComplete per direct.

Laten we het nu bespreken handleLoadComplete functie die ik net noemde:

 function handleLoadComplete (event) totalLoaded ++; if (manifest.length == totalLoaded) addTitleView (); 

Het is een vrij eenvoudige functie; we verhogen de totalLoaded variabele (die het aantal geladen items tot nu toe bevat) en dan controleren we of het aantal items in ons manifest hetzelfde is als het aantal geladen items, en zo ja, ga dan naar het hoofdmenuscherm.


Stap 5: Het hoofdmenu maken

 function addTitleView () //console.log("Titelweergave toevoegen "); startB.x = 240 - 31.5; startB.y = 160; startB.name = 'startB'; creditsB.x = 241 - 42; creditsB.y = 200; TitleView.addChild (main, startB, creditsB); stage.addChild (bg, TitleView); stage.update (); // Knopluisteraars startB.onPress = tweenTitleView; creditsB.onPress = showCredits;

Niets bijzonders hier. We plaatsen de afbeeldingen van de knop Achtergrond, Startknop en Credits op het podium en koppelen onPress gebeurtenishandlers naar de knoppen Start en Credits.

Hier zijn de functies die het scherm met credits weergeven en verwijderen tweenTitleView die het spel start:

 function showCredits () // Toon credits credits.x = 480; stage.addChild (credits); stage.update (); Tween.get (credits) .to (x: 0, 300); credits.onPress = hideCredits;  // Verberg Credits-functie hideCredits (e) Tween.get (credits) .to (x: 480, 300) .call (rmvCredits);  // Functie Credits verwijderen rmvCredits () stage.removeChild (credits);  // Tween Title View-functie tweenTitleView () // Start Game Tween.get (TitleView) .to (y: -320, 300) .call (addGameView); 

Stap 6: De spelcode

We hebben het grootste deel van deze zelfstudie bereikt, namelijk de code van het spel zelf.

Allereerst moeten we alle vereiste assets aan het podium toevoegen, dus dat doen we in de addGameView functie:

 functie addGameView () // Vernietig Menu & Credits scherm stage.removeChild (TitleView); TitleView = null; credits = null; // Voeg Game View player.x = 2 toe; player.y = 160 - 37.5; cpu.x = 480 - 25; cpu.y = 160 - 37.5; ball.x = 240 - 15; ball.y = 160 - 15; // Score playerScore = nieuwe tekst ('0', 'bold 20px Arial', '# A3FF24'); playerScore.x = 211; playerScore.y = 20; cpuScore = nieuwe tekst ('0', 'bold 20px Arial', '# A3FF24'); cpuScore.x = 262; cpuScore.y = 20; stage.addChild (playerScore, cpuScore, player, cpu, ball); stage.update (); // Start Listener bg.onPress = startGame; 

Nogmaals, een vrij eenvoudige functie die de objecten op het scherm plaatst en een mouseEvent aan de achtergrondafbeelding toevoegt, zodat wanneer de gebruiker erop klikt, het spel zal starten (we zullen de start het spel functie).

Laten we het bekijken start het spel functie:

 function startGame (e) bg.onPress = null; stage.onMouseMove = movePaddle; Ticker.addListener (tkr, false); tkr.tick = update; 

Hier, zoals u kunt zien, naast het toevoegen van een onMouseMove evenement dat onze peddel beweegt. We voegen het toe Kruis aan evenement, dat het bijwerken functie in elk frame.

Laten we het bekijken movePaddle en reset functies:

 functie movePaddle (e) // Muisbeweging player.y = e.stageY;  / * Reset * / functie-reset () ball.x = 240 - 15; ball.y = 160 - 15; player.y = 160 - 37.5; cpu.y = 160 - 37.5; stage.onMouseMove = null; Ticker.removeListener (TKR); bg.onPress = startspel; 

In movePaddle, we plaatsen in feite de paddle van de gebruiker op de y-coördinaat van de muis.

In reset, we doen iets soortgelijks addGameView, behalve hier voegen we geen grafische elementen toe, omdat ze al op het scherm staan.

De ... gebruiken alarm functie zullen we de winnende en verliezende popup weergeven:

 functie alert (e) Ticker.removeListener (tkr); stage.onMouseMove = null; bg.onPress = null if (e == 'win') win.x = 140; win.y = -90; stage.addChild (win); Tween.get (win) .to (y: 115, 300);  else lose.x = 140; lose.y = -90; stage.addChild (verliezen); Tween.get (verliest) .to (y: 115, 300); 

Stap 7: The Game Loop

Nu, voor het laatste deel van onze tutorial werken we aan de bijwerken functie (die in elk frame van het spel voorkomt - vergelijkbaar met Flash's onEnterFrame):

 functie-update () // Balverplaatsing ball.x = ball.x + xSpeed; ball.y = ball.y + ySpeed; // Cpu-beweging indien (cpu.y < ball.y)  cpu.y = cpu.y + 4;  else if(cpu.y > ball.y) cpu.y = cpu.y - 4;  // Wall Collision if ((ball.y) < 0)  ySpeed = -ySpeed; SoundJS.play('wall'); ;//Up if((ball.y + (30)) > 320) ySpeed ​​= -ySpeed; SoundJS.play ('wall');; // down / * CPU-score * / if ((ball.x) < 0)  xSpeed = -xSpeed; cpuScore.text = parseInt(cpuScore.text + 1); reset(); SoundJS.play('enemyScore');  /* Player Score */ if((ball.x + (30)) > 480) xSpeed ​​= -xSpeed; playerScore.text = parseInt (playerScore.text + 1); reset (); SoundJS.play (playerScore);  / * Cpu-botsing * / if (ball.x + 30> cpu.x && ball.x + 30 < cpu.x + 22 && ball.y >= cpu.y && ball.y < cpu.y + 75)  xSpeed *= -1; SoundJS.play('hit');  /* Player collision */ if(ball.x <= player.x + 22 && ball.x > player.x && ball.y> = player.y && ball.y < player.y + 75)  xSpeed *= -1; SoundJS.play('hit');  /* Stop Paddle from going out of canvas */ if(player.y >= 249) player.y = 249;  / * Check for Win * / if (playerScore.text == '10') alert ('win');  / * Controleer of Game Over * / if (cpuScore.text == '10') alert ('lose'); 

Ziet er eng uit, nietwaar? Maak je geen zorgen, we zullen elk onderdeel bekijken en bespreken.

 // Balverplaatsing ball.x = bal.x + xSpeed; ball.y = ball.y + ySpeed;

In elk frame beweegt de bal volgens de x- en y-snelheidswaarden

 // Cpu-beweging if ((cpu.y + 32) < (ball.y-14))  cpu.y = cpu.y + cpuSpeed;  else if((cpu.y+32) > (ball.y + 14)) cpu.y = cpu.y - cpuSpeed; 

Hier hebben we de basis-AI van de computer, waarbij de paddle van de computer eenvoudig de bal volgt zonder speciale logica. We vergelijken gewoon de locatie van het midden van de paddle (vandaar dat we 32 pixels toevoegen aan de cpu Y-waarde) naar de locatie van de bal, met een kleine offset, en verplaatsen de paddle indien nodig naar boven of beneden..

 if ((bal.y) < 0)  //top ySpeed = -ySpeed; SoundJS.play('wall'); ; if((ball.y + (30)) > 320) // bottom ySpeed ​​= -ySpeed; SoundJS.play ( 'wand'); ;

Als de bal de bovenrand of de onderrand van het scherm raakt, verandert de bal van richting en spelen we het Wall Hit-geluid.

 / * CPU-score * / if ((ball.x) < 0)  xSpeed = -xSpeed; cpuScore.text = parseInt(cpuScore.text + 1); reset(); SoundJS.play('enemyScore');  /* Player Score */ if((ball.x + (30)) > 480) xSpeed ​​= -xSpeed; playerScore.text = parseInt (playerScore.text + 1); reset (); SoundJS.play (playerScore); 

De score-login is eenvoudig: als de bal de linker- of rechtergrenzen passeert, verhoogt deze de score van respectievelijk de speler of de CPU, speelt een geluid af en stelt de locatie van de objecten opnieuw in met behulp van de reset functie die we eerder hebben besproken.

 / * CPU-botsing * / if (ball.x + 30> cpu.x && ball.x + 30 < cpu.x + 22 && ball.y >= cpu.y && ball.y < cpu.y + 75)  xSpeed *= -1; SoundJS.play('hit');  /* Player collision */ if(ball.x <= player.x + 22 && ball.x > player.x && ball.y> = player.y && ball.y < player.y + 75)  xSpeed *= -1; SoundJS.play('hit'); 

Hier hebben we te maken met botsingen van de bal met de peddels; elke keer dat de bal een van de paddles raakt, verandert de bal van richting en wordt er een geluid gespeeld

 if (player.y> = 249) player.y = 249; 

Als de paddle van de speler buiten de grenzen raakt, plaatsen we deze binnen de grenzen.

 / * Check for Win * / if (playerScore.text == '10') alert ('win');  / * Controleer of Game Over * / if (cpuScore.text == '10') alert ('lose'); 

In dit fragment controleren we of de score van een van de spelers 10 punten heeft bereikt en als dat het geval is, tonen we de winnende of verliezende pop-up aan de speler (afhankelijk van zijn winnende status).


Conclusie

Dat is alles, je hebt een volledig pongspel gemaakt met CreateJS. Bedankt dat je de tijd hebt genomen om deze tutorial te lezen.