Maak een Pong-spel in HTML5 met EaselJS

In deze zelfstudie maken we een kloon van het klassieke spel, Pong, in HTML5, met behulp van de Easel JS-bibliotheek. De game heeft meerdere schermen, geluidseffecten en een (zeer eenvoudige) AI-tegenstander.

Stap 1: Kort overzicht

Met behulp van vooraf gemaakte afbeeldingen coderen we een leuke pong spel in HTML5 met de Easel JS-bibliotheek, die een Flash-achtige interface voor het HTML5-canvas biedt. Zie dit Activetuts + -artikel voor een inleiding tot EaselJS.

De speler kan een paddle besturen met de muis en tegen de tegenstander van de computer-controller spelen om punten te krijgen.


Stap 2: Interface

Een eenvoudige interface met een neo-futuristische stijl zal worden gebruikt; dit omvat meerdere vormen, knoppen, bitmaps en meer.

De grafische voorstellingen voor deze tutorial zijn te vinden in de bijgevoegde download.


Stap 3: download EaselJS

De EaselJS-bibliotheek zal worden gebruikt om ons spel te bouwen, zorg ervoor dat je de Ermee beginnen zelfstudie als u nog niet bekend bent met deze bibliotheek.

U kunt de nieuwste versie van EaselJS downloaden van de officiële website. Dit kan hier echter incompatibel zijn met de code, dus ik raad aan om de versie van de bibliotheek te gebruiken die bij de brondownload is inbegrepen.


Stap 4: HTML-structuur

Laten we ons HTML-document voorbereiden. We beginnen met de basisprincipes, alleen een overzicht van barebones:

    pong    

Stap 5: Verberg Mobile Highlight

We moeten ook een klein beetje CSS toevoegen om de standaardmarkering te verwijderen die wordt toegepast wanneer u op een element in een mobiele browser tikt. Zonder dit zou de mobiele ervaring drastisch afnemen.

    pong     

Stap 6: Javascript-bibliotheken

De volgende code voegt de nodige javascript-bibliotheken toe om onze app te laten werken.

    pong         /

Naast EaselJS gebruiken we ook TweenJS (voor het omgaan met schermovergangen en de gamelus) en SoundJS (voor de geluidseffecten).

main.js is het bestand dat we zullen gebruiken om onze eigen JS-code te houden.


Stap 7: Hoofdfunctie oproepen

In de volgende regels noemen we onze Hoofd() functie. Dit is de functie waarmee onze applicatie wordt gestart; het wordt later in de zelfstudie, binnen gemaakt main.js.

    pong         

Stap 8: Canvastag

Een HTML5-canvas wordt op deze regel gemaakt; we kennen het een ID toe zodat we er later naar kunnen verwijzen en ook de breedte en hoogte ervan kunnen instellen.

    pong          

Stap 9: Maak Main.js

Laten we beginnen met het maken van games!

Open de JavaScript-editor van uw voorkeur (elke teksteditor werkt, maar u hoeft geen syntax te markeren) en bereid u voor op het schrijven van de code. Vergeet niet om het bestand op te slaan als main.js in je projectmap.


Stap 10: Definieer Canvas

We beginnen met het definiëren van alle grafische en logische variabelen.

De volgende variabelen vertegenwoordigen het HTML-canvaselement en de fase die eraan wordt gekoppeld. De stadium variabele zal zich op dezelfde manier gedragen als de AS3-fase.

 / * Definieer Canvas * / var canvas; var stadium;

Stap 11: Achtergrond

Deze variabele slaat de titelachtergrond op.

 / * Achtergrond * / var bgImg = new Image (); var bg;

Stap 12: Titeloverzicht

Dit is de titelweergave, het eerste interactieve scherm dat in onze game verschijnt. Deze variabelen slaan de componenten op.

 / * Titelweergave * / var mainImg = new Image (); var main; var startBImg = new Image (); var startB; var creditsBImg = new Image (); var creditsB; var TitleView = nieuwe container ();

Stap 13: Credits

In deze weergave worden de aftiteling, het jaar en het auteursrecht van het spel weergegeven. Deze variabelen worden gebruikt om het spel op te slaan.

 / * Credits * / var creditsViewImg = new Image (); var credits;

Stap 14: Spelweergave

In de volgende variabelen worden de afzonderlijke afbeeldingen opgeslagen die in de gameweergave worden weergegeven:

 / * Spelweergave * / var playerImg = nieuw afbeelding (); var speler; var ballImg = new Image (); var bal; var cpuImg = new Image (); var cpu; var winImg = new Image (); var win; var loseImg = new Image (); var verliezen;

Stap 15: Score

De scorewaarden worden afgehandeld door de volgende variabelen:

 / * Score * / var playerScore; var cpuScore;

Stap 16: Variabelen

Dit zijn de variabelen die we zullen gebruiken, lees de opmerkingen in de code om te begrijpen waarvoor ze zijn:

 var xSpeed ​​= 5; // Horizontale snelheid van de bal var ySpeed ​​= 5; // Verticale snelheid van de bal var gfxLoaded = 0; // gebruikt als een preloader, telt de reeds geladen items var tkr = new Object; // gebruikt als gebeurtenislistener voor de Ticker

Stap 17: Geluidseffecten maken

We zullen geluidseffecten gebruiken om het gevoel van het spel te verbeteren. De geluiden in dit voorbeeld zijn gemaakt met de uitstekende gratis tool as3sfxr en geconverteerd naar MP3 met Audacity.

De benodigde geluiden zijn allemaal te vinden in de brondownload. Als je je eigen wilt maken, heb je er vier nodig:

  • hit.mp3: gespeeld wanneer de bal een peddel raakt
  • playerScore.mp3: gespeeld wanneer ze speler scoort
  • enemyScore.mp3: gespeeld wanneer de vijand scoort
  • wall.mp3: gespeeld wanneer de bal de boven- of ondergrens raakt

Stap 18: Hoofdfunctie

De Hoofd() functie zal als eerste worden uitgevoerd wanneer de webpagina wordt geladen, omdat er naar wordt verwezen in de onload kenmerk van het HTML-document (zie stap 7).

Het zal de nodige functies oproepen om het spel te starten.

 function Main () // code ...

Stap 19: Link Canvas

Deze code krijgt de HTML-canvas-ID en koppelt deze aan de EaselJS Stage-klasse. Hierdoor zal de stage-variabele zich gedragen als de stage-klasse in AS3. Voeg dit toe aan Hoofd().

 / * Link Canvas * / canvas = document.getElementById ('Pong'); stage = nieuwe Stage (canvas);

Stap 20: Schakel muisgebeurtenissen in

Muisgebeurtenissen zijn standaard uitgeschakeld in EaselJS om de prestaties te verbeteren. Omdat we die in het spel nodig hebben, voegen we de volgende regel toe. Voeg dit toe aan Hoofd().

 stage.mouseEventsEnabled = true;

Stap 21: Laad geluiden

We gebruiken SoundJS om geluiden aan onze game toe te voegen; schrijf de volgende code om de geluiden te importeren die we zullen gebruiken. Voeg dit toe aan Hoofd().

 / * Geluid * / SoundJS.addBatch ([name: 'hit', src: 'hit.mp3', instanties: 1, naam: 'playerScore', src: 'playerScore.mp3', instanties: 1, name: 'enemyScore', src: 'enemyScore.mp3', instanties: 1, name: 'wall', src: 'wall.mp3', exemplaren: 1]);

Stap 22: grafische afbeeldingen laden

Deze code wordt gebruikt om de afbeeldingen vooraf te laden met behulp van een functie die we later zullen schrijven. Hiermee worden de afbeeldingsobjecten ingesteld die we eerder hebben gemaakt om te verwijzen naar de relevante bron-PNG-bestanden in onze documentenmap.

Aan elk wordt een naam gegeven, zodat we kunnen detecteren welk beeld later wordt geladen en tot slot de functie die de geladen afbeeldingen afhandelt.

Voeg dit toe aan Hoofd().

 / * Laad GFX * / bgImg.src = 'bg.png'; bgImg.name = 'bg'; bgImg.onload = loadGfx; mainImg.src = 'main.png'; mainImg.name = 'main'; mainImg.onload = loadGfx; startBImg.src = 'startB.png'; startBImg.name = 'startB'; startBImg.onload = loadGfx; creditsBImg.src = 'creditsB.png'; creditsBImg.name = 'creditsB'; creditsBImg.onload = loadGfx; creditsViewImg.src = 'credits.png'; creditsViewImg.name = 'credits'; creditsViewImg.onload = loadGfx; playerImg.src = 'paddle.png'; playerImg.name = 'speler'; playerImg.onload = loadGfx; ballImg.src = 'ball.png'; ballImg.name = 'bal'; ballImg.onload = loadGfx; cpuImg.src = 'paddle.png'; cpuImg.name = 'cpu'; cpuImg.onload = loadGfx; winImg.src = 'win.png'; winImg.name = 'win'; winImg.onload = loadGfx; loseImg.src = 'lose.png'; loseImg.name = 'verliezen'; loseImg.onload = loadGfx;

Stap 23: Stel Ticker in

De Ticker-klasse biedt een gecentraliseerde vink of heartbeat die met een ingesteld interval wordt uitgezonden. Dit kan worden gebruikt om de gamelus te activeren.

De volgende code stelt de framesnelheid in op 30 en definieert de stage als de listener voor de ticks.

De TweenJS-klasse luistert naar deze teek om de animaties uit te voeren. Voeg dit toe aan Hoofd().

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

Stap 24: Preload-functie

Elke keer dat een afbeelding wordt geladen, wordt deze functie uitgevoerd. Het wijst elke afbeelding toe aan een bitmapobject en controleert of alle elementen zijn geladen voordat verder wordt gegaan.

 functie loadGfx (e) if (e.target.name = 'bg') bg = nieuwe Bitmap (bgImg); if (e.target.name = 'main') main = new Bitmap (mainImg); if (e.target.name = 'startB') startB = new Bitmap (startBImg); if (e.target.name = 'creditsB') creditsB = new Bitmap (creditsBImg); if (e.target. name = 'credits') credits = nieuwe Bitmap (creditsViewImg); if (e.target.name = 'player') player = nieuwe Bitmap (playerImg); if (e.target.name = 'ball') ball = new Bitmap (ballImg); if (e.target.name = 'cpu') cpu = new Bitmap (cpuImg); if (e.target.name = 'win') win = new Bitmap ( winImg); if (e.target.name = 'lose') lose = new Bitmap (loseImg); gfxLoaded ++; if (gfxLoaded == 10) // vergeet dit niet te veranderen als u meer afbeeldingen toevoegt addTitleView (); 

Stap 25: Titelweergave toevoegen

Wanneer alle afbeeldingen zijn geladen, wordt de titelweergave aan het werkgebied toegevoegd met de volgende functie:

 function addTitleView () 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 ();

Stap 26: Start Button Luisteraars

Deze functie voegt de nodige luisteraars toe aan de TitleView knoppen (het maakt deel uit van addTitleView ()):

 startB.onPress = addGameView; creditsB.onPress = showCredits; 

Stap 27: Toon credits

De credits scherm wordt getoond wanneer de gebruiker op de knop credits klikt; een muisluisteraar wordt toegevoegd aan de volledige afbeelding om deze te verwijderen.

 function showCredits () // Toon credits credits.x = 480; stage.addChild (credits); stage.update (); Tween.get (credits) .to (x: 0, 300); credits.onPress = hideCredits; 

Stap 28: Verberg tegoeden

Wanneer de credits op het scherm wordt geklikt, het wordt terug getweend en van het werkgebied verwijderd.

 // Hide Credits function hideCredits (e) Tween.get (credits) .to (x: 480, 300) .call (rmvCredits);  // Functie Credits verwijderen rmvCredits () stage.removeChild (credits); 

Laten we hier stoppen om te testen wat we tot nu toe hebben gedaan. Klik hier voor een mijlpaaldemo.

Houd er rekening mee dat sommige regels zijn weggelaten omdat sommige functies nog niet zijn gemaakt.

Vergeet niet dat de mijlpaal is opgenomen in de bronbestanden, dus als om wat voor reden dan ook uw bestand deze niet nabootst, vergelijk dan uw bron met de mijne om te zien wat de oorzaak zou kunnen zijn.


Stap 29: Spelweergave tonen

De volgende regels verwijderen de TitleView van het podium en voegt de GameView items naar het podium. Een muisluisteraar wordt toegevoegd aan de achtergrond om het spel te starten wanneer erop wordt geklikt.

 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.maxWidth = 1000; // fix voor Chrome 17 playerScore.x = 211; playerScore.y = 20; cpuScore = nieuwe tekst ('0', 'bold 20px Arial', '# A3FF24'); cpuScore.maxWidth = 1000; // fix voor Chrome 17 cpuScore.x = 262; cpuScore.y = 20; stage.addChild (playerScore, cpuScore, player, cpu, ball); stage.update (); // Start Listener bg.onPress = startGame; 

Stap 30: Spelersbeweging

De speler beweegt mee met de verticale positie van de muis:

 functie movePaddle (e) // Muisbeweging player.y = e.stageY; 

Stap 31: Start Game

Deze code wordt uitgevoerd wanneer de speler op de achtergrond van het spel klikt, het voegt de muislistener toe die de functie in de vorige stap activeert, en voegt een lichtkrant toe om de spellus te besturen.

Besteed aandacht aan de manier waarop de ticker is gemaakt: het is het equivalent van een timergebeurtenis in AS3.

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

Stap 32: Reset

Wanneer een punt wordt gescoord (door de speler of de computer), keren de paddles en de bal terug naar hun oorspronkelijke posities en wordt het spel onderbroken:

 functie reset () ball.x = 240 - 15; ball.y = 160 - 15; player.y = 160 - 37.5; cpu.y = 160 - 37.5; stage.onMouseMove = null; // stop met luisteren naar de muis Ticker.removeListener (tkr); // pauzeer het spel bg.onPress = startspel; 

Stap 33: Balverplaatsing

Als het spel niet is gepauzeerd, wordt de bal elk frame verplaatst met behulp van de variabelen die we eerder hebben gemaakt.

 functie-update () // Balverplaatsing ball.x = ball.x + xSpeed; ball.y = ball.y + ySpeed;

Stap 34: CPU-beweging

Deze code regelt de beweging van de computer; de peddel wordt zodanig bewogen dat deze de bal volgt terwijl er nog steeds een foutmarge is.

 if (cpu.y < ball.y)  cpu.y = cpu.y + 2.5;  else if(cpu.y > ball.y) cpu.y = cpu.y - 2.5; 

Stap 35: Muurbotsingen

Hier controleren we of de bal zich aan de boven- of onderrand van het canvas bevindt; in dat geval wordt de verticale snelheid omgekeerd en klinkt er een geluid.

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

Stap 36: Scores

Nu de linker- en rechterkant. Deze code wijzigt ook de score, roept de reset-functie aan en speelt een ander geluid afhankelijk van de kant die de bal heeft aangeraakt.

 / * 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); 

Stap 37: Ball-Paddle-botsingen

De volgende code controleert of de bal botst met een paddle, door de positie van de paddle te vergelijken met de coördinaten van de bal. Als de selectiekaders van de twee elkaar kruisen, is er een botsing, dus we keren de x-snelheid van de bal om en spelen een geluid.

 / * 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'); 

Stap 38: Controleer op Win / Game Over

U kunt de eindvoorwaarde in de volgende regels wijzigen - deze is standaard ingesteld op 10 punten.

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

Stap 39: Waarschuwing

Deze functie zal het spel stoppen en een waarschuwing weergeven, waarvan de inhoud afhangt van het spelresultaat.

 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 40: Test

Sla je werk op (als je dat nog niet hebt gedaan) en open het HTML-bestand in de browser om te zien hoe je game werkt!


Conclusie

Probeer de variabelen van de game aan te passen om uw eigen versie van de game te maken!

Ik hoop dat je deze tutorial leuk vond, bedankt voor het lezen!