You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Web-Dev-For-Beginners/translations/sk/6-space-game/3-moving-elements-around
leestott c0ca49b2cc
🌐 Update translations via Co-op Translator
3 weeks ago
..
README.md 🌐 Update translations via Co-op Translator 3 weeks ago
assignment.md 🌐 Update translations via Co-op Translator 3 weeks ago

README.md

Vytvorenie vesmírnej hry, časť 3: Pridanie pohybu

Kvíz pred prednáškou

Kvíz pred prednáškou

Hry nie sú veľmi zábavné, kým sa na obrazovke nezačnú pohybovať mimozemšťania! V tejto hre využijeme dva typy pohybov:

  • Pohyb klávesnicou/myšou: keď používateľ interaguje s klávesnicou alebo myšou na pohyb objektu na obrazovke.
  • Pohyb vyvolaný hrou: keď hra pohybuje objektom v určitých časových intervaloch.

Ako teda pohybujeme vecami na obrazovke? Všetko je to o karteziánskych súradniciach: zmeníme polohu (x, y) objektu a potom prekreslíme obrazovku.

Typicky potrebujete nasledujúce kroky na dosiahnutie pohybu na obrazovke:

  1. Nastaviť novú polohu objektu; to je potrebné na to, aby sa objekt javil, že sa pohybuje.
  2. Vyčistiť obrazovku, obrazovka musí byť vyčistená medzi jednotlivými prekresleniami. Môžeme ju vyčistiť nakreslením obdĺžnika, ktorý vyplníme farbou pozadia.
  3. Prekresliť objekt na novej polohe. Týmto konečne dosiahneme pohyb objektu z jednej polohy na druhú.

Takto to môže vyzerať v kóde:

//set the hero's location
hero.x += 5;
// clear the rectangle that hosts the hero
ctx.clearRect(0, 0, canvas.width, canvas.height);
// redraw the game background and hero
ctx.fillRect(0, 0, canvas.width, canvas.height)
ctx.fillStyle = "black";
ctx.drawImage(heroImg, hero.x, hero.y);

Dokážete si predstaviť dôvod, prečo by prekresľovanie vášho hrdinu mnohokrát za sekundu mohlo spôsobiť výkonové náklady? Prečítajte si o alternatívach k tomuto vzoru.

Spracovanie udalostí klávesnice

Udalosti spracovávate pripojením konkrétnych udalostí ku kódu. Udalosti klávesnice sa spúšťajú na celom okne, zatiaľ čo udalosti myši, ako napríklad click, môžu byť pripojené ku kliknutiu na konkrétny prvok. Počas tohto projektu budeme používať udalosti klávesnice.

Na spracovanie udalosti musíte použiť metódu addEventListener() okna a poskytnúť jej dva vstupné parametre. Prvým parametrom je názov udalosti, napríklad keyup. Druhým parametrom je funkcia, ktorá by sa mala spustiť ako výsledok udalosti.

Tu je príklad:

window.addEventListener('keyup', (evt) => {
  // `evt.key` = string representation of the key
  if (evt.key === 'ArrowUp') {
    // do something
  }
})

Pre udalosti klávesnice existujú dve vlastnosti na udalosti, ktoré môžete použiť na zistenie, ktorá klávesa bola stlačená:

  • key, toto je reťazcová reprezentácia stlačenej klávesy, napríklad ArrowUp.
  • keyCode, toto je číselná reprezentácia, napríklad 37, čo zodpovedá ArrowLeft.

Manipulácia s udalosťami klávesnice je užitočná aj mimo vývoja hier. Na aké iné použitia tejto techniky dokážete myslieť?

Špeciálne klávesy: upozornenie

Existujú niektoré špeciálne klávesy, ktoré ovplyvňujú okno. To znamená, že ak počúvate udalosť keyup a použijete tieto špeciálne klávesy na pohyb vášho hrdinu, vykoná sa aj horizontálne posúvanie. Z tohto dôvodu možno budete chcieť vypnúť toto vstavané správanie prehliadača, keď budete budovať svoju hru. Potrebujete kód ako tento:

let onKeyDown = function (e) {
  console.log(e.keyCode);
  switch (e.keyCode) {
    case 37:
    case 39:
    case 38:
    case 40: // Arrow keys
    case 32:
      e.preventDefault();
      break; // Space
    default:
      break; // do not block other keys
  }
};

window.addEventListener('keydown', onKeyDown);

Vyššie uvedený kód zabezpečí, že šípky a medzerník budú mať svoje predvolené správanie vypnuté. Mechanizmus vypnutia sa spustí, keď zavoláme e.preventDefault().

Pohyb vyvolaný hrou

Veci môžeme nechať pohybovať sa samé pomocou časovačov, ako sú funkcie setTimeout() alebo setInterval(), ktoré aktualizujú polohu objektu pri každom tiknutí alebo časovom intervale. Takto to môže vyzerať:

let id = setInterval(() => {
  //move the enemy on the y axis
  enemy.y += 10;
})

Herná slučka

Herná slučka je koncept, ktorý v podstate predstavuje funkciu, ktorá sa spúšťa v pravidelných intervaloch. Nazýva sa herná slučka, pretože všetko, čo by malo byť viditeľné pre používateľa, sa kreslí v rámci tejto slučky. Herná slučka využíva všetky herné objekty, ktoré sú súčasťou hry, a kreslí ich, pokiaľ z nejakého dôvodu už nie sú súčasťou hry. Napríklad, ak je objekt nepriateľ, ktorý bol zasiahnutý laserom a exploduje, už nie je súčasťou aktuálnej hernej slučky (o tom sa dozviete viac v nasledujúcich lekciách).

Takto môže typická herná slučka vyzerať, vyjadrená v kóde:

let gameLoopId = setInterval(() =>
  function gameLoop() {
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    ctx.fillStyle = "black";
    ctx.fillRect(0, 0, canvas.width, canvas.height);
    drawHero();
    drawEnemies();
    drawStaticObjects();
}, 200);

Vyššie uvedená slučka sa spúšťa každých 200 milisekúnd na prekreslenie plátna. Máte možnosť zvoliť si najlepší interval, ktorý dáva zmysel pre vašu hru.

Pokračovanie vo vesmírnej hre

Vezmete existujúci kód a rozšírite ho. Buď začnite s kódom, ktorý ste dokončili počas časti I, alebo použite kód v časti II - štartér.

  • Pohyb hrdinu: pridáte kód na zabezpečenie pohybu hrdinu pomocou šípok.
  • Pohyb nepriateľov: budete tiež musieť pridať kód na zabezpečenie pohybu nepriateľov zhora nadol v danom tempe.

Odporúčané kroky

Nájdite súbory, ktoré boli pre vás vytvorené v podpriečinku your-work. Mali by obsahovať nasledujúce:

-| assets
  -| enemyShip.png
  -| player.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; zatiaľ sa nič nehýbe!

Pridajte kód

  1. Pridajte špecifické objekty pre hero, enemy a game object, mali by mať vlastnosti x a y. (Pamätajte na časť o Dedičnosti alebo kompozícii).

    TIP: game object by mal byť ten, ktorý má x a y a schopnosť kresliť sa na plátno.

    tip: začnite pridaním novej triedy GameObject s jej konštruktorom, ako je uvedené nižšie, a potom ju nakreslite na plátno:

    
    class GameObject {
      constructor(x, y) {
        this.x = x;
        this.y = y;
        this.dead = false;
        this.type = "";
        this.width = 0;
        this.height = 0;
        this.img = undefined;
      }
    
      draw(ctx) {
        ctx.drawImage(this.img, this.x, this.y, this.width, this.height);
      }
    }
    

    Teraz rozšírte tento GameObject na vytvorenie Hero a Enemy.

    class Hero extends GameObject {
      constructor(x, y) {
        ...it needs an x, y, type, and speed
      }
    }
    
    class Enemy extends GameObject {
      constructor(x, y) {
        super(x, y);
        (this.width = 98), (this.height = 50);
        this.type = "Enemy";
        let id = setInterval(() => {
          if (this.y < canvas.height - this.height) {
            this.y += 5;
          } else {
            console.log('Stopped at', this.y)
            clearInterval(id);
          }
        }, 300)
      }
    }
    
  2. Pridajte spracovanie udalostí klávesnice na spracovanie navigácie klávesami (pohyb hrdinu hore/dole, vľavo/vpravo).

    PAMÄTAJTE: ide o karteziánsky systém, ľavý horný roh je 0,0. Tiež nezabudnite pridať kód na zastavenie predvoleného správania.

    tip: vytvorte svoju funkciu onKeyDown a pripojte ju k oknu:

     let onKeyDown = function (e) {
           console.log(e.keyCode);
             ...add the code from the lesson above to stop default behavior
           }
     };
    
     window.addEventListener("keydown", onKeyDown);
    

    Skontrolujte konzolu prehliadača v tomto bode a sledujte, ako sa zaznamenávajú stlačenia kláves.

  3. Implementujte Pub sub vzor, ktorý udrží váš kód čistý, keď budete pokračovať v ďalších častiach.

    Na vykonanie tejto poslednej časti môžete:

    1. Pridať poslucháča udalostí na okno:

       window.addEventListener("keyup", (evt) => {
         if (evt.key === "ArrowUp") {
           eventEmitter.emit(Messages.KEY_EVENT_UP);
         } else if (evt.key === "ArrowDown") {
           eventEmitter.emit(Messages.KEY_EVENT_DOWN);
         } else if (evt.key === "ArrowLeft") {
           eventEmitter.emit(Messages.KEY_EVENT_LEFT);
         } else if (evt.key === "ArrowRight") {
           eventEmitter.emit(Messages.KEY_EVENT_RIGHT);
         }
       });
      
    2. Vytvoriť triedu EventEmitter na publikovanie a odoberanie správ:

      class EventEmitter {
        constructor() {
          this.listeners = {};
        }
      
        on(message, listener) {
          if (!this.listeners[message]) {
            this.listeners[message] = [];
          }
          this.listeners[message].push(listener);
        }
      
        emit(message, payload = null) {
          if (this.listeners[message]) {
            this.listeners[message].forEach((l) => l(message, payload));
          }
        }
      }
      
    3. Pridať konštanty a nastaviť EventEmitter:

      const Messages = {
        KEY_EVENT_UP: "KEY_EVENT_UP",
        KEY_EVENT_DOWN: "KEY_EVENT_DOWN",
        KEY_EVENT_LEFT: "KEY_EVENT_LEFT",
        KEY_EVENT_RIGHT: "KEY_EVENT_RIGHT",
      };
      
      let heroImg, 
          enemyImg, 
          laserImg,
          canvas, ctx, 
          gameObjects = [], 
          hero, 
          eventEmitter = new EventEmitter();
      
    4. Inicializovať hru

    function initGame() {
      gameObjects = [];
      createEnemies();
      createHero();
    
      eventEmitter.on(Messages.KEY_EVENT_UP, () => {
        hero.y -=5 ;
      })
    
      eventEmitter.on(Messages.KEY_EVENT_DOWN, () => {
        hero.y += 5;
      });
    
      eventEmitter.on(Messages.KEY_EVENT_LEFT, () => {
        hero.x -= 5;
      });
    
      eventEmitter.on(Messages.KEY_EVENT_RIGHT, () => {
        hero.x += 5;
      });
    }
    
  4. Nastaviť hernú slučku

    Refaktorujte funkciu window.onload na inicializáciu hry a nastavenie hernej slučky v dobrom intervale. Tiež pridáte laserový lúč:

    window.onload = async () => {
      canvas = document.getElementById("canvas");
      ctx = canvas.getContext("2d");
      heroImg = await loadTexture("assets/player.png");
      enemyImg = await loadTexture("assets/enemyShip.png");
      laserImg = await loadTexture("assets/laserRed.png");
    
      initGame();
      let gameLoopId = setInterval(() => {
        ctx.clearRect(0, 0, canvas.width, canvas.height);
        ctx.fillStyle = "black";
        ctx.fillRect(0, 0, canvas.width, canvas.height);
        drawGameObjects(ctx);
      }, 100)
    
    };
    
  5. Pridajte kód na pohyb nepriateľov v určitých intervaloch.

    Refaktorujte funkciu createEnemies() na vytvorenie nepriateľov a ich pridanie do novej triedy gameObjects:

    function createEnemies() {
      const MONSTER_TOTAL = 5;
      const MONSTER_WIDTH = MONSTER_TOTAL * 98;
      const START_X = (canvas.width - MONSTER_WIDTH) / 2;
      const STOP_X = START_X + MONSTER_WIDTH;
    
      for (let x = START_X; x < STOP_X; x += 98) {
        for (let y = 0; y < 50 * 5; y += 50) {
          const enemy = new Enemy(x, y);
          enemy.img = enemyImg;
          gameObjects.push(enemy);
        }
      }
    }
    

    a pridajte funkciu createHero() na vykonanie podobného procesu pre hrdinu.

    function createHero() {
      hero = new Hero(
        canvas.width / 2 - 45,
        canvas.height - canvas.height / 4
      );
      hero.img = heroImg;
      gameObjects.push(hero);
    }
    

    a nakoniec pridajte funkciu drawGameObjects() na spustenie kreslenia:

    function drawGameObjects(ctx) {
      gameObjects.forEach(go => go.draw(ctx));
    }
    

    Vaši nepriatelia by mali začať postupovať na vašu vesmírnu loď!


🚀 Výzva

Ako vidíte, váš kód sa môže zmeniť na "špagetový kód", keď začnete pridávať funkcie, premenné a triedy. Ako môžete lepšie organizovať svoj kód, aby bol čitateľnejší? Návrhnite systém na organizáciu vášho kódu, aj keď stále zostáva v jednom súbore.

Kvíz po prednáške

Kvíz po prednáške

Recenzia a samoštúdium

Aj keď píšeme našu hru bez použitia frameworkov, existuje mnoho JavaScriptových frameworkov pre vývoj hier na báze plátna. Nájdite si čas na čítanie o nich.

Zadanie

Okomentujte svoj kód


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.