11 KiB
Vytvorenie vesmírnej hry, časť 4: Pridanie lasera a detekcia kolízií
Kvíz pred prednáškou
V tejto lekcii sa naučíte, ako strieľať lasery pomocou JavaScriptu! Do našej hry pridáme dve veci:
- Laser: tento laser sa vystrelí z lode hrdinu a pohybuje sa vertikálne nahor
- Detekcia kolízií, ako súčasť implementácie schopnosti strieľať, pridáme aj niekoľko pravidiel hry:
- Laser zasiahne nepriateľa: Nepriateľ zomrie, ak ho zasiahne laser
- Laser zasiahne hornú časť obrazovky: Laser sa zničí, ak zasiahne hornú časť obrazovky
- Kolízia nepriateľa a hrdinu: Nepriateľ aj hrdina sa zničia, ak sa zrazia
- Nepriateľ zasiahne spodnú časť obrazovky: Nepriateľ aj hrdina sa zničia, ak nepriateľ zasiahne spodnú časť obrazovky
Stručne povedané, vy -- hrdina -- musíte zasiahnuť všetkých nepriateľov laserom skôr, než sa dostanú na spodnú časť obrazovky.
✅ Urobte si malý prieskum o úplne prvej počítačovej hre, ktorá bola kedy napísaná. Aká bola jej funkčnosť?
Buďme hrdinami spolu!
Detekcia kolízií
Ako vykonáme detekciu kolízií? Musíme si predstaviť naše herné objekty ako obdĺžniky, ktoré sa pohybujú. Prečo? Pretože obrázok použitý na vykreslenie herného objektu je obdĺžnik: má x
, y
, šírku
a výšku
.
Ak sa dva obdĺžniky, napríklad hrdina a nepriateľ, pretínajú, máte kolíziu. Čo by sa malo stať, závisí od pravidiel hry. Na implementáciu detekcie kolízií potrebujete nasledovné:
-
Spôsob, ako získať obdĺžnikovú reprezentáciu herného objektu, niečo takéto:
rectFromGameObject() { return { top: this.y, left: this.x, bottom: this.y + this.height, right: this.x + this.width } }
-
Porovnávaciu funkciu, ktorá môže vyzerať takto:
function intersectRect(r1, r2) { return !(r2.left > r1.right || r2.right < r1.left || r2.top > r1.bottom || r2.bottom < r1.top); }
Ako ničíme objekty
Na zničenie objektov v hre musíte dať hre vedieť, že tento objekt už nemá byť vykreslený v hernej slučke, ktorá sa spúšťa v určitých intervaloch. Spôsob, ako to urobiť, je označiť herný objekt ako mŕtvy, keď sa niečo stane, napríklad takto:
// collision happened
enemy.dead = true
Potom môžete vyradiť mŕtve objekty pred opätovným vykreslením obrazovky, napríklad takto:
gameObjects = gameObject.filter(go => !go.dead);
Ako vystreliť laser
Vystrelenie lasera znamená reagovať na udalosť stlačenia klávesy a vytvoriť objekt, ktorý sa pohybuje určitým smerom. Preto musíme vykonať nasledujúce kroky:
- Vytvoriť objekt lasera: z vrchnej časti lode hrdinu, ktorý sa po vytvorení začne pohybovať nahor smerom k hornej časti obrazovky.
- Pripojiť kód k udalosti stlačenia klávesy: musíme vybrať kláves na klávesnici, ktorý bude predstavovať hráča strieľajúceho laser.
- Vytvoriť herný objekt, ktorý vyzerá ako laser, keď je kláves stlačený.
Časový odstup pre laser
Laser musí vystreliť vždy, keď stlačíte kláves, napríklad medzerník. Aby sme zabránili hre vytvárať príliš veľa laserov v krátkom čase, musíme to opraviť. Oprava spočíva v implementácii tzv. časového odstupu, časovača, ktorý zabezpečí, že laser môže byť vystrelený len v určitých intervaloch. Môžete to implementovať nasledovne:
class Cooldown {
constructor(time) {
this.cool = false;
setTimeout(() => {
this.cool = true;
}, time)
}
}
class Weapon {
constructor {
}
fire() {
if (!this.cooldown || this.cooldown.cool) {
// produce a laser
this.cooldown = new Cooldown(500);
} else {
// do nothing - it hasn't cooled down yet.
}
}
}
✅ Pozrite si lekciu 1 zo série vesmírnych hier, aby ste si pripomenuli časové odstupy.
Čo vytvoriť
Vezmete existujúci kód (ktorý by ste mali vyčistiť a refaktorovať) z predchádzajúcej lekcie a rozšírite ho. Buď začnite s kódom z časti II, alebo použite kód na Časť III - štartovací.
tip: laser, s ktorým budete pracovať, je už vo vašom priečinku s prostriedkami a je referencovaný vaším kódom
- Pridajte detekciu kolízií, keď laser narazí na niečo, mali by platiť nasledujúce pravidlá:
- Laser zasiahne nepriateľa: nepriateľ zomrie, ak ho zasiahne laser
- Laser zasiahne hornú časť obrazovky: laser sa zničí, ak zasiahne hornú časť obrazovky
- Kolízia nepriateľa a hrdinu: nepriateľ aj hrdina sa zničia, ak sa zrazia
- Nepriateľ zasiahne spodnú časť obrazovky: nepriateľ aj hrdina sa zničia, ak nepriateľ zasiahne spodnú časť obrazovky
Odporúčané kroky
Vyhľadajte súbory, ktoré boli pre vás vytvorené v podpriečinku your-work
. Mali by obsahovať nasledovné:
-| assets
-| enemyShip.png
-| player.png
-| laserRed.png
-| index.html
-| app.js
-| package.json
Svoj projekt spustíte v priečinku your_work
zadaním:
cd your-work
npm start
Vyššie uvedené spustí HTTP server na adrese http://localhost:5000
. Otvorte prehliadač a zadajte túto adresu, momentálne by sa mal zobraziť hrdina a všetci nepriatelia, nič sa však ešte nehýbe :).
Pridajte kód
-
Nastavte obdĺžnikovú reprezentáciu vášho herného objektu na spracovanie kolízií Nasledujúci kód umožňuje získať obdĺžnikovú reprezentáciu
GameObject
. Upraviť triedu GameObject tak, aby ju rozšírila:rectFromGameObject() { return { top: this.y, left: this.x, bottom: this.y + this.height, right: this.x + this.width, }; }
-
Pridajte kód, ktorý kontroluje kolízie Toto bude nová funkcia, ktorá testuje, či sa dva obdĺžniky pretínajú:
function intersectRect(r1, r2) { return !( r2.left > r1.right || r2.right < r1.left || r2.top > r1.bottom || r2.bottom < r1.top ); }
-
Pridajte schopnosť vystreliť laser
-
Pridajte správu o udalosti stlačenia klávesy. Kláves medzerník by mal vytvoriť laser tesne nad loďou hrdinu. Pridajte tri konštanty do objektu Messages:
KEY_EVENT_SPACE: "KEY_EVENT_SPACE", COLLISION_ENEMY_LASER: "COLLISION_ENEMY_LASER", COLLISION_ENEMY_HERO: "COLLISION_ENEMY_HERO",
-
Spracujte kláves medzerník. Upraviť funkciu
window.addEventListener
pre stlačenie klávesy, aby spracovala medzerník:} else if(evt.keyCode === 32) { eventEmitter.emit(Messages.KEY_EVENT_SPACE); }
-
Pridajte poslucháčov. Upraviť funkciu
initGame()
, aby hrdina mohol strieľať, keď je stlačený medzerník:eventEmitter.on(Messages.KEY_EVENT_SPACE, () => { if (hero.canFire()) { hero.fire(); }
a pridajte novú funkciu
eventEmitter.on()
, aby ste zabezpečili správanie, keď nepriateľ narazí na laser:eventEmitter.on(Messages.COLLISION_ENEMY_LASER, (_, { first, second }) => { first.dead = true; second.dead = true; })
-
Pohyb objektu, Zabezpečte, aby sa laser postupne pohyboval k hornej časti obrazovky. Vytvoríte novú triedu Laser, ktorá rozširuje
GameObject
, ako ste to už urobili predtým:class Laser extends GameObject { constructor(x, y) { super(x,y); (this.width = 9), (this.height = 33); this.type = 'Laser'; this.img = laserImg; let id = setInterval(() => { if (this.y > 0) { this.y -= 15; } else { this.dead = true; clearInterval(id); } }, 100) } }
-
Spracujte kolízie, Implementujte pravidlá kolízií pre laser. Pridajte funkciu
updateGameObjects()
, ktorá testuje objekty na kolízie:function updateGameObjects() { const enemies = gameObjects.filter(go => go.type === 'Enemy'); const lasers = gameObjects.filter((go) => go.type === "Laser"); // laser hit something lasers.forEach((l) => { enemies.forEach((m) => { if (intersectRect(l.rectFromGameObject(), m.rectFromGameObject())) { eventEmitter.emit(Messages.COLLISION_ENEMY_LASER, { first: l, second: m, }); } }); }); gameObjects = gameObjects.filter(go => !go.dead); }
Uistite sa, že ste pridali
updateGameObjects()
do hernej slučky vwindow.onload
. -
Implementujte časový odstup pre laser, aby mohol byť vystrelený len v určitých intervaloch.
Nakoniec upravte triedu Hero tak, aby mala časový odstup:
class Hero extends GameObject { constructor(x, y) { super(x, y); (this.width = 99), (this.height = 75); this.type = "Hero"; this.speed = { x: 0, y: 0 }; this.cooldown = 0; } fire() { gameObjects.push(new Laser(this.x + 45, this.y - 10)); this.cooldown = 500; let id = setInterval(() => { if (this.cooldown > 0) { this.cooldown -= 100; } else { clearInterval(id); } }, 200); } canFire() { return this.cooldown === 0; } }
-
V tomto bode má vaša hra určitú funkčnosť! Môžete sa pohybovať pomocou šípok, strieľať laser pomocou medzerníka a nepriatelia zmiznú, keď ich zasiahnete. Skvelá práca!
🚀 Výzva
Pridajte explóziu! Pozrite sa na herné prostriedky v repozitári Space Art a skúste pridať explóziu, keď laser zasiahne mimozemšťana.
Kvíz po prednáške
Prehľad a samostatné štúdium
Experimentujte s intervalmi vo vašej hre doteraz. Čo sa stane, keď ich zmeníte? Prečítajte si viac o časových udalostiach v JavaScripte.
Zadanie
Upozornenie:
Tento dokument bol preložený pomocou služby na automatický preklad Co-op Translator. Hoci sa snažíme o presnosť, upozorňujeme, že automatické preklady môžu obsahovať chyby alebo nepresnosti. Pôvodný dokument v jeho pôvodnom jazyku by mal byť považovaný za autoritatívny zdroj. Pre kritické informácie sa odporúča profesionálny ľudský preklad. Nezodpovedáme za akékoľvek nedorozumenia alebo nesprávne interpretácie vyplývajúce z použitia tohto prekladu.