Skip to content

Latest commit

 

History

History
890 lines (714 loc) · 35.9 KB

File metadata and controls

890 lines (714 loc) · 35.9 KB

Izrada igre u svemiru, dio 3: Dodavanje gibanja

journey
    title Vaše putovanje animacijom igre
    section Osnove kretanja
      Razumjeti principe pokreta: 3: Student
      Naučiti ažuriranja koordinata: 4: Student
      Implementirati osnovno kretanje: 4: Student
    section Kontrole igrača
      Rukovati događajima tipkovnice: 4: Student
      Spriječiti zadane radnje: 5: Student
      Kreirati responzivne kontrole: 5: Student
    section Sustavi igre
      Izgraditi petlju igre: 5: Student
      Upravljati životnim ciklusom objekata: 5: Student
      Implementirati pub/sub obrazac: 5: Student
Loading

Razmislite o svojim omiljenim igrama – ono što ih čini privlačnima nije samo lijepa grafika, već način na koji se sve kreće i reagira na vaše radnje. Trenutno je vaša igra u svemiru poput prekrasne slike, ali upravo ćemo dodati pokret koji će joj udahnuti život.

Kada su inženjeri NASA-e programirali računalo za upravljanje za Apolonske misije, suočili su se sličnim izazovom: kako natjerati svemirski brod da reagira na upravljanje pilotom dok istovremeno automatski održava korekcije kursa? Principi koje ćemo danas naučiti odražavaju te iste koncepte – upravljanje kretanjem kojim kontrolira igrač uz automatsko ponašanje sustava.

U ovom ćemo lekciji naučiti kako učiniti da se svemirski brodovi klize preko ekrana, reagiraju na zapovijedi igrača i stvaraju glatke uzorke kretanja. Sve ćemo razbiti na upravljive koncepte koji se prirodno nadovezuju jedan na drugi.

Na kraju će igrači moći letjeti svojim herojskim brodom po ekranu dok neprijateljski brodovi patroliraju iznad. Još važnije, razumjet ćete temeljne principe koji pokreću sustave kretanja u igrama.

mindmap
  root((Game Animation))
    Vrste Gibanja
      Igrač Kontrolira
      Automatski Pokret
      Fizika Temeljena
      Skriptirane Staze
    Obrada Događaja
      Tipkovnički Unosi
      Miševi Događaji
      Dodirne Kontrole
      Sprečavanje Zadano
    Petlja Igre
      Ažuriranje Logike
      Renderiranje Okvira
      Čišćenje Platna
      Kontrola Brzine Okvira
    Upravljanje Objektima
      Ažuriranje Položaja
      Detekcija Sudara
      Upravljanje Životnim Ciklusom
      Praćenje Stanja
    Komunikacija
      Pub/Sub Uzorak
      Emitteri Događaja
      Prosljeđivanje Poruka
      Labavo Povezivanje
Loading

Kviz prije predavanja

Kviz prije predavanja

Razumijevanje gibanja u igrama

Igre oživljavaju kada stvari počnu kretati, a postoje osnovno dva načina na koja se to događa:

  • Kretanje koje kontrolira igrač: Kad pritisnete tipku ili kliknete mišem, nešto se pomiče. To je izravna veza između vas i vašeg svijeta igre.
  • Automatsko kretanje: Kada igra sama odlučuje pomaknuti stvari – poput onih neprijateljskih brodova koji moraju patrolirati ekranskim prostorom bez obzira na to radite li išta ili ne.

Pomicanje objekata na računalu je jednostavnije nego što mislite. Sjećate li se onih x i y koordinata iz matematičke nastave? Upravo s tim radimo ovdje. Kad je Galileo 1610. pratilo Jupiterove mjesece, on je ustvari radio isto – bilježio položaje tijekom vremena da bi razumio obrasce gibanja.

Pomicanje stvari na ekranu je poput stvaranja animacije kao u flipbooku – morate pratiti ova tri jednostavna koraka:

flowchart LR
    A["Frejm N"] --> B["Ažuriraj pozicije"]
    B --> C["Očisti platno"]
    C --> D["Nacrtaj objekte"]
    D --> E["Frejm N+1"]
    E --> F{Nastaviti?}
    F -->|Da| B
    F -->|Ne| G["Kraj igre"]
    
    subgraph "Ciklus animacije"
        H["1. Izračunaj nove pozicije"]
        I["2. Izbriši prethodni frejm"]
        J["3. Prikaži novi frejm"]
    end
    
    style B fill:#e1f5fe
    style C fill:#ffebee
    style D fill:#e8f5e8
Loading
  1. Ažurirajte poziciju – Promijenite mjesto na kojem vaš objekt treba biti (možda ga premjestite 5 piksela udesno)
  2. Izbrišite stari okvir – Očistite ekran da ne biste vidjeli duhove tragova svuda oko
  3. Nacrtajte novi okvir – Postavite svoj objekt na novo mjesto

Učinite to dovoljno brzo, i bum! Dobivate glatko kretanje koje igračima djeluje prirodno.

Ovako to može izgledati u kodu:

// Postavi lokaciju heroja
hero.x += 5;
// Očisti pravokutnik koji sadrži heroja
ctx.clearRect(0, 0, canvas.width, canvas.height);
// Ponovno nacrtaj pozadinu igre i heroja
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = "black";
ctx.drawImage(heroImg, hero.x, hero.y);

Ovo što radi ovaj kod:

  • Ažurira x-koordinatu heroja za 5 piksela da se pomakne horizontalno
  • Briše cijeli canvas da ukloni prethodni okvir
  • Popunjava canvas crnom pozadinom
  • Ponovno crta sliku heroja na njegovoj novoj poziciji

✅ Možete li smisliti razlog zašto bi ponovno crtanje heroja mnogo puta u sekundi moglo trošiti performanse? Pročitajte o alternativama ovom uzorku.

Rukovanje događajima tipkovnice

Ovdje povezujemo unos igrača i akciju u igri. Kad netko pritisne razmaknicu da puca laserom ili pritisne strelicu da izbjegne asteroid, vaša igra mora detektirati i odgovoriti na taj unos.

Događaji s tipkovnice događaju se na razini prozora, što znači da cijeli vaš prozor preglednika sluša te pritiske tipki. Klikovi mišem, s druge strane, mogu biti vezani za specifične elemente (poput klika na gumb). Za našu svemirsku igru fokusirat ćemo se na kontrole s tipkovnice jer one igračima daju onaj klasični arkadni osjećaj.

Ovo me podsjeća na to kako su telegrafisti u 1800-ima morali prevoditi unos Morseove abecede u smislene poruke – mi radimo nešto slično, pretvaramo pritiske tipki u naredbe igre.

Da biste rukovali događajem, trebate koristiti metodu addEventListener() prozora i pružiti joj dva ulazna parametra. Prvi parametar je ime događaja, na primjer keyup. Drugi parametar je funkcija koja se treba pozvati kao rezultat događaja.

Evo primjera:

window.addEventListener('keyup', (evt) => {
  // evt.key = nizovni prikaz tipke
  if (evt.key === 'ArrowUp') {
    // učini nešto
  }
});

Razbijajući što se događa ovdje:

  • Sluša događaje s tipkovnice na cijelom prozoru
  • Hvata objekt događaja koji sadrži informacije o tome koja je tipka pritisnuta
  • Provjerava je li pritisnuta tipka jednaka određenoj tipki (u ovom slučaju strelica gore)
  • Izvršava kod kad je uvjet zadovoljen

Za događaje s tipkovnice postoje dva svojstva na događaju koja možete koristiti da vidite koja je tipka pritisnuta:

  • key - ovo je tekstualni prikaz pritisnute tipke, na primjer 'ArrowUp'
  • keyCode - ovo je brojčani prikaz, na primjer 37, odgovara ArrowLeft

✅ Manipulacija događajima tipkovnice korisna je i izvan razvoja igara. Koje druge primjene možete smisliti za ovu tehniku?

sequenceDiagram
    participant User
    participant Browser
    participant EventSystem
    participant GameLogic
    participant Hero
    
    User->>Browser: Pritisne tipku ArrowUp
    Browser->>EventSystem: keydown događaj
    EventSystem->>EventSystem: preventDefault()
    EventSystem->>GameLogic: emit('KEY_EVENT_UP')
    GameLogic->>Hero: hero.y -= 5
    Hero->>Hero: Ažuriraj poziciju
    
    Note over Browser,GameLogic: Tijek događaja sprječava zadane postavke preglednika
    Note over GameLogic,Hero: Pub/sub obrazac omogućava čistu komunikaciju
Loading

Posebne tipke: upozorenje!

Neke tipke imaju ugrađena ponašanja u pregledniku koja mogu ometati vašu igru. Strelice pomiču stranicu, a razmaknica skakuće dolje – ponašanja koja ne želite kada netko pokušava pilotirati svoj svemirski brod.

Možemo spriječiti ta zadana ponašanja i dopustiti našoj igri da umjesto toga obrađuje unos. Ovo je slično kako su rani programeri računala morali ignorirati prekide sustava da bi stvorili prilagođena ponašanja – samo što sad to radimo na razini preglednika. Evo kako:

const onKeyDown = function (e) {
  console.log(e.keyCode);
  switch (e.keyCode) {
    case 37:
    case 39:
    case 38:
    case 40: // Tipke sa strelicama
    case 32:
      e.preventDefault();
      break; // Razmak
    default:
      break; // ne blokiraj ostale tipke
  }
};

window.addEventListener('keydown', onKeyDown);

Razumijevanje ovog koda za sprječavanje:

  • Provjerava specifične kodove tipki koje bi mogle uzrokovati neželjeno ponašanje preglednika
  • Sprječava zadanu akciju preglednika za strelice i razmaknicu
  • Dopušta ostalim tipkama da funkcioniraju normalno
  • Koristi e.preventDefault() da zaustavi ugrađeno ponašanje preglednika

🔄 Pedagoški pregled

Razumijevanje rukovanja događajima: Prije nego prijeđete na automatsko kretanje, budite sigurni da možete:

  • ✅ Objasniti razliku između događaja keydown i keyup
  • ✅ Razumjeti zašto sprječavamo zadana ponašanja preglednika
  • ✅ Opisati kako slušači događaja povezuju unos korisnika s logikom igre
  • ✅ Prepoznati koje tipke bi mogle ometati kontrole igre

Brzi samoprovjera: Što bi se dogodilo da ne spriječite zadano ponašanje za strelice? Odgovor: Preglednik bi pomicao stranicu, što bi ometalo kretanje u igri

Arhitektura sustava događaja: Sada razumijete:

  • Slušanje na razini prozora: hvatanje događaja na razini preglednika
  • Svojstva objekta događaja: stringovi key protiv brojeva keyCode
  • Sprječavanje zadanog: zaustavljanje neželjenih ponašanja preglednika
  • Uvjetna logika: reagiranje na određene kombinacije tipki

Kretanje uzrokovano igrom

Sad razgovarajmo o objektima koji se kreću bez unosa igrača. Razmislite o neprijateljskim brodovima koji krstare ekranom, metcima koji lete ravno ili oblacima koji plutaju u pozadini. Ovo autonomno kretanje čini vaš svijet igre živim čak i kad nitko ne dira kontrole.

Koristimo ugrađene JavaScript timere da ažuriramo pozicije u redovitim intervalima. Ovaj koncept sličan je radu klatna na satu – redoviti mehanizam koji pokreće dosljedne, vremenski određene radnje. Evo koliko to može biti jednostavno:

const id = setInterval(() => {
  // Pomakni neprijatelja na y osi
  enemy.y += 10;
}, 100);

Ovo što radi ovaj kod za kretanje:

  • Stvara timer koji se izvršava svakih 100 milisekundi
  • Ažurira y-koordinatu neprijatelja za 10 piksela svaki put
  • Spremi ID intervala kako bismo ga mogli zaustaviti kasnije ako treba
  • Automatski pomiče neprijatelja prema dolje na ekranu

Petlja igre

Evo koncepta koji sve povezuje – petlja igre. Da je vaša igra film, petlja igre bila bi filmski projektor koji prikazuje kadar za kadrom tako brzo da sve izgleda glatko.

Svaka igra ima jednu takvu petlju koja radi u pozadini. To je funkcija koja ažurira sve objekte igre, ponovno crta ekran i neprestano ponavlja taj proces. Ona prati vašeg heroja, sve neprijatelje, laserske zrake – cijelo stanje igre.

Ovaj koncept me podsjeća na to kako su rani animatorii poput Walta Disneya morali ponovno crtati likove kadar po kadar da stvaraju iluziju kretanja. Mi radimo isto, samo umjesto olovaka koristimo kod.

Ovako obično može izgledati petlja igre, izražena u kodu:

flowchart TD
    A["Pokreni petlju igre"] --> B["Očisti platno"]
    B --> C["Ispuni pozadinu"]
    C --> D["Ažuriraj objekte igre"]
    D --> E["Nacrtaj heroja"]
    E --> F["Nacrtaj neprijatelje"]
    F --> G["Nacrtaj UI elemente"]
    G --> H["Čekaj sljedeći kadar"]
    H --> I{Je li igra pokrenuta?}
    I -->|Da| B
    I -->|Ne| J["Završi igru"]
    
    subgraph "Kontrola frekvencije sličica"
        K["60 FPS = 16.67ms"]
        L["30 FPS = 33.33ms"]
        M["10 FPS = 100ms"]
    end
    
    style B fill:#ffebee
    style D fill:#e1f5fe
    style E fill:#e8f5e8
    style F fill:#e8f5e8
Loading
const 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();
  }
  gameLoop();
}, 200);

Razumijevanje strukture petlje igre:

  • Briše cijeli canvas da ukloni prethodni kadar
  • Popunjava pozadinu solidnom bojom
  • Crta sve objekte igre na njihovim trenutačnim pozicijama
  • Ponavlja ovaj proces svakih 200 milisekundi da stvori glatku animaciju
  • Upravljanje brzinom prikaza kadrova pomoću kontroliranja intervala

Nastavak svemirske igre

Sad ćemo dodati kretanje statičnoj sceni koju ste prethodno izgradili. Pretvorit ćemo je iz snimke zaslona u interaktivno iskustvo. Proći ćemo korak po korak kako bi svaki dio prirodno slijedio prethodni.

Uzmite kod odakle smo stali u prošloj lekciji (ili započnite s kodom u Part II- starter mapi ako treba svježi početak).

Ovo što danas gradimo:

  • Herojske kontrole: Strelice će upravljati vašim svemirskim brodom po ekranu
  • Neprijateljsko kretanje: Ti izvanzemaljski brodovi započet će svoj napredak

Krenimo s implementacijom tih značajki.

Preporučeni koraci

Pronađite datoteke koje su pripremljene za vas u podmapi your-work. Trebale bi sadržavati sljedeće:

-| assets
  -| enemyShip.png
  -| player.png
-| index.html
-| app.js
-| package.json

Projekt započinjete u mapi your-work upisivanjem:

cd your-work
npm start

Što ova naredba radi:

  • Navigira u direktorij vašeg projekta
  • Pokreće HTTP poslužitelj na adresi http://localhost:5000
  • Servira vaše datoteke igre kako biste ih mogli testirati u pregledniku

Gорје navedenim bit će pokrenut HTTP poslužitelj na adresi http://localhost:5000. Otvorite preglednik i upišite tu adresu, trenutno bi trebala prikazati heroja i sve neprijatelje; još ništa ne miče se - zasad!

Dodajte kod

  1. Dodajte posebne objekte za hero, enemy i game object, trebaju imati svojstva x i y. (Sjetite se dijela o nasljeđivanju ili kompoziciji).

    NAPOMENA game object treba biti onaj s x i y te sposobnošću crtanja na canvas.

    Savjet: Započnite dodavanjem nove klase GameObject s konstruktorom kao u nastavku, a zatim je nacrtajte na canvas:

    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);
      }
    }

    Razumijevanje ove osnovne klase:

    • Definira zajednička svojstva koja dijele svi objekti igre (položaj, veličina, slika)
    • Uključuje zastavicu dead koja prati treba li objekt ukloniti
    • Omogućuje metodu draw() koja prikazuje objekt na canvasu
    • Postavlja zadane vrijednosti za sva svojstva koja djeca klase mogu nadjačati
classDiagram
    class GameObject {
        +x: broj
        +y: broj
        +dead: boolean
        +type: string
        +width: broj
        +height: broj
        +img: Image
        +draw(ctx)
    }
    
    class Hero {
        +speed: broj
        +type: "Hero"
        +width: 98
        +height: 75
    }
    
    class Enemy {
        +type: "Enemy"
        +width: 98
        +height: 50
        +setInterval()
    }
    
    GameObject <|-- Hero
    GameObject <|-- Enemy
    
    class EventEmitter {
        +listeners: objekt
        +on(message, listener)
        +emit(message, payload)
    }
Loading
Sada, proširite `GameObject` da biste napravili `Hero` i `Enemy`:

```javascript
class Hero extends GameObject {
  constructor(x, y) {
    super(x, y);
    this.width = 98;
    this.height = 75;
    this.type = "Hero";
    this.speed = 5;
  }
}
```

```javascript
class Enemy extends GameObject {
  constructor(x, y) {
    super(x, y);
    this.width = 98;
    this.height = 50;
    this.type = "Enemy";
    const id = setInterval(() => {
      if (this.y < canvas.height - this.height) {
        this.y += 5;
      } else {
        console.log('Stopped at', this.y);
        clearInterval(id);
      }
    }, 300);
  }
}
```

**Ključni koncepti u ovim klasama:**
- **Nasljeđuje** iz `GameObject` koristeći ključnu riječ `extends`
- **Poziva** konstruktor roditelja s `super(x, y)`
- **Postavlja** specifične dimenzije i svojstva za svaki tip objekta
- **Implementira** automatsko kretanje neprijatelja koristeći `setInterval()`
  1. Dodajte rukovatelje događajima za tipke da biste upravljali kretanjem heroja gore/dolje lijevo/desno

    Sjetite se da je to kartezični sustav, gornji lijevi kut je 0,0. Također ne zaboravite dodati kod za zaustavljanje zadanog ponašanja

    Savjet: Napravite svoju funkciju onKeyDown i pridružite ju prozoru:

    const onKeyDown = function (e) {
      console.log(e.keyCode);
      // Dodajte kod iz prethodne lekcije za zaustavljanje zadane radnje
      switch (e.keyCode) {
        case 37:
        case 39:
        case 38:
        case 40: // Tipke sa strelicama
        case 32:
          e.preventDefault();
          break; // Razmak
        default:
          break; // ne blokirajte druge tipke
      }
    };
    
    window.addEventListener("keydown", onKeyDown);

    Ovo što ovaj rukovatelj događajima radi:

    • Sluša događaje pritiska tipke na cijelom prozoru
    • Zapisuje kod tipke da vam pomogne s otklanjanjem pogrešaka koje tipke se pritiskaju
    • Sprječava zadano ponašanje preglednika za strelice i razmaknicu
    • Dopušta ostalim tipkama da rade normalno

    Provjerite konzolu preglednika u ovom trenutku i promatrajte bilježenje pritisnutih tipki.

  2. Implementirajte Pub sub uzorak, ovo će održati vaš kod čistim dok pratite ostatak dijelova.

    Publish-Subscribe uzorak pomaže organizirati vaš kod odvajanjem detekcije događaja od rukovanja događajem. Čini vaš kod modularnijim i lakšim za održavanje.

    Za ovu zadnju fazu, možete:

    1. Dodajte slušača događaja na prozor:

      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);
        }
      });

    Ovo što ovaj sustav događaja radi:

    • Detektira unos s tipkovnice i pretvara ga u prilagođene događaje igre
    • Razdvaja detekciju unosa od logike igre
    • Olakšava izmjenu kontrola kasnije bez utjecaja na kod igre
    • Dopušta da se isti unos koristi za više sustava
flowchart TD
    A["Unos s tipkovnice"] --> B["Slušatelj događaja prozora"]
    B --> C["Emiter događaja"]
    C --> D["TIPKA_DOGAĐAJ_GORE"]
    C --> E["TIPKA_DOGAĐAJ_DOLJE"]
    C --> F["TIPKA_DOGAĐAJ_LIJEVO"]
    C --> G["TIPKA_DOGAĐAJ_DESNO"]
    
    D --> H["Kretanje junaka"]
    D --> I["Sustav zvuka"]
    D --> J["Vizualni efekti"]
    
    E --> H
    F --> H
    G --> H
    
    style A fill:#e1f5fe
    style C fill:#e8f5e8
    style H fill:#fff3e0
Loading
  1. Napravite klasu EventEmitter za objavljivanje i pretplatu na poruke:

    class EventEmitter {
      constructor() {
        this.listeners = {};
      }
    
      on(message, listener) {
        if (!this.listeners[message]) {
          this.listeners[message] = [];
        }
        this.listeners[message].push(listener);
      }
  2. Dodajte konstante i postavite 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();

Razumijevanje postavki:

  • Definira konstante poruka da bi se izbjegle tipfeler i olakšala refaktorizacija
  • Deklarira varijable za slike, kontekst canvasa i stanje igre
  • Stvara globalnog emitera događaja za sustav pub-sub
  • Inicijalizira polje za pohranu svih objekata igre
  1. Inicijaliziraj igru

    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;
      });
  2. Postavi petlju igre

    Preuredi funkciju window.onload kako bi inicijalizirala igru i postavila petlju igre s dobrim intervalom. Također ćeš dodati laserski snop:

    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();
      const gameLoopId = setInterval(() => {
        ctx.clearRect(0, 0, canvas.width, canvas.height);
        ctx.fillStyle = "black";
        ctx.fillRect(0, 0, canvas.width, canvas.height);
        drawGameObjects(ctx);
      }, 100);
    };

    Razumijevanje postavljanja igre:

    • Čeka da se stranica potpuno učita prije početka
    • Dohvaća element canvas i njegov 2D rendering kontekst
    • Učitava sve slikovne resurse asinkrono pomoću await
    • Pokreće petlju igre koja radi na intervalima od 100 ms (10 FPS)
    • Briše i ponovno crta cijeli zaslon svaki frame
  3. Dodaj kod za pomicanje neprijatelja u određenom intervalu

    Preuredi funkciju createEnemies() da stvori neprijatelje i ubaci ih u novu klasu 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);
        }
      }
    }

    Što kreiranje neprijatelja radi:

    • Izračunava pozicije kako bi neprijatelji bili centrirani na zaslonu
    • Stvara mrežu neprijatelja koristeći ugniježdene petlje
    • Dodjeljuje sliku neprijatelja svakom objektu neprijatelja
    • Dodaje svakog neprijatelja globalnom polju game objekata

    te dodaj funkciju createHero() koja radi sličan proces za heroja.

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

    Što kreiranje heroja radi:

    • Pozicionira heroja na donji centar zaslona
    • Dodjeljuje herojevu sliku hero objektu
    • Dodaje heroja u polje game objekata za prikazivanje

    i na kraju, dodaj funkciju drawGameObjects() za početak crtanja:

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

    Razumijevanje funkcije crtanja:

    • Prolazi kroz sve game objekte u polju
    • Poziva metodu draw() za svaki objekt
    • Prosljeđuje kontekst platna kako bi se objekti mogli prikazati

    🔄 Pedagoški pregled

    Potpuno razumijevanje sistema igre: Provjeri svoje znanje o cijeloj arhitekturi:

    • ✅ Kako nasljeđivanje omogućuje Hero i Enemy da dijele zajednička svojstva GameObject-a?
    • ✅ Zašto pub/sub obrazac čini tvoj kod lakše održivim?
    • ✅ Koju ulogu igra petlja igre u stvaranju glatke animacije?
    • ✅ Kako event listeneri povezuju korisnički unos s ponašanjem objekata u igri?

    Integracija sustava: Tvoja igra sada demonstrira:

    • Objektno orijentirani dizajn: Osnovne klase sa specijaliziranim nasljeđivanjem
    • Arhitektura vođena događajima: Pub/sub obrazac za labavu povezanost
    • Okvir za animaciju: Petlja igre s dosljednim ažuriranjima frameova
    • Rukovanje unosom: Tipkovni događaji s onemogućavanjem default ponašanja
    • Upravljanje resursima: Učitavanje slika i rendering spriteova

    Profesionalni obrasci: Implementirao si:

    • Odvajanje odgovornosti: Logika, unos i prikaz su odvojeni
    • Polimorfizam: Svi game objekti dijele zajedničko sučelje za crtanje
    • Slanje poruka: Čista komunikacija između komponenti
    • Upravljanje resursima: Učinkovito rukovanje spriteovima i animacijama

    Tvoji neprijatelji bi trebali početi napredovati prema tvom hero svemirskom brodu! } }

    
    and add a `createHero()` function to do a similar process for the hero.
    
    ```javascript
    function createHero() {
      hero = new Hero(
        canvas.width / 2 - 45,
        canvas.height - canvas.height / 4
      );
      hero.img = heroImg;
      gameObjects.push(hero);
    }
    

    i na kraju, dodaj funkciju drawGameObjects() za početak crtanja:

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

    Tvoji neprijatelji bi trebali početi napredovati prema tvom hero svemirskom brodu!


GitHub Copilot Agent Izazov 🚀

Evo izazova koji će poboljšati polirani izgled tvoje igre: dodavanje granica i glatkih kontrola. Trenutno tvoj heroj može odletjeti s ekrana, a kretanje može izgledati isprekidano.

Tvoja misija: Učini da tvoj svemirski brod izgleda realističnije implementirajući granice ekrana i tečno kretanje. Ovo je slično kao kako NASA-in sustav upravljanja letom sprječava da svemirske letjelice prelaze sigurne operativne parametre.

Evo što trebaš napraviti: Kreiraj sustav koji drži tvoj hero svemirski brod na ekranu i učini kontrole glatkim. Kada igrači drže pritisnutu tipku strelice, brod bi trebao kliziti kontinuirano umjesto da se pomiče u diskretnim koracima. Razmotri dodavanje vizualne povratne informacije kada brod dosegne granice ekrana – možda diskretan efekt koji označava rub područja igre.

Saznaj više o agent modu ovdje.

🚀 Izazov

Organizacija koda postaje sve važnija kako projekti rastu. Možda si primijetio da tvoja datoteka postaje zatrpana funkcijama, varijablama i klasama pomiješanim zajedno. To me podsjeća na to kako su inženjeri koji su organizirali Apollo misiju morali stvoriti jasne, održive sustave na kojima je moglo istovremeno raditi više timova.

Tvoja misija: Razmišljaj kao softverski arhitekt. Kako bi organizirao svoj kod da bi ga nakon šest mjeseci ti (ili kolega) mogao razumjeti? Čak i ako sve ostane u jednoj datoteci za sada, možeš stvoriti bolju organizaciju:

  • Grupiranje povezanih funkcija s jasnim komentarima zaglavlja
  • Odvajanje odgovornosti – drži logiku igre odvojenu od prikaza
  • Korištenje dosljedne terminologije za varijable i funkcije
  • Kreiranje modula ili namespaceova za organizaciju različitih aspekata igre
  • Dodavanje dokumentacije koja objašnjava svrhu svakog većeg dijela

Pitanja za razmišljanje:

  • Koji dijelovi tvog koda su najteži za razumjeti kada se vratiš na njih?
  • Kako bi organizirao svoj kod da bi nekome drugome bilo lakše doprinijeti?
  • Što bi se dogodilo da želiš dodati nove značajke poput pojačanja ili različitih tipova neprijatelja?

Kviz poslije predavanja

Post-lecture quiz

Pregled i samostalno učenje

Izgrađivali smo sve ispočetka, što je fantastično za učenje, ali evo male tajne – postoje neki izvrsni JavaScript frameworkovi koji mogu obaviti puno tog teškog posla za tebe. Kad se osjećaš ugodno s temeljima koje smo pokrili, vrijedi istražiti što je dostupno.

Zamislite frameworkove kao dobro opremljeni alatni set umjesto da svaki alat izrađuješ ručno. Oni mogu riješiti mnoge izazove organizacije koda o kojima smo razgovarali, plus ponuditi značajke koje bi ti same gradile tjednima.

Vrijedi istražiti:

  • Kako igraći motori organiziraju kod – bit ćeš zadivljen pametnim obrascima koje koriste
  • Trikove za performanse kako bi igre na canvasu išle glatko
  • Moderne JavaScript značajke koje mogu učiniti tvoj kod čišćim i održivijim
  • Različite pristupe upravljanju objektima igre i njihovim odnosima

🎯 Tvoj vremenski plan za usavršavanje animacije igre

timeline
    title Napredak u učenju animacije i interakcije u igri
    
    section Osnove kretanja (20 minuta)
        Osnove animacije: Animacija bazirana na okvirima
                        : Ažuriranja položaja
                        : Koordinatni sustavi
                        : Glatko kretanje
        
    section Sustavi događaja (25 minuta)
        Korisnički unos: Rukovanje događajima tipkovnice
                      : Sprječavanje zadane radnje
                      : Svojstva objekta događaja
                      : Slušanje na razini prozora
        
    section Arhitektura igre (30 minuta)
        Dizajn objekata: Obrasci nasljeđivanja
                        : Izrada osnovne klase
                        : Specijalizirana ponašanja
                        : Polimorfni sučelja
        
    section Obrasci komunikacije (35 minuta)
        Implementacija Pub/Sub: Emitteri događaja
                              : Konstante poruka
                              : Labava povezanost
                              : Integracija sustava
        
    section Ovladavanje petljom igre (40 minuta)
        Sustavi u stvarnom vremenu: Kontrola brzine okvira
                                  : Ciklus ažuriranja/renderiranja
                                  : Upravljanje stanjima
                                  : Optimizacija performansi
        
    section Napredne tehnike (45 minuta)
        Profesionalne značajke: Detekcija kolizije
                             : Simulacija fizike
                             : Stroj stanja
                             : Sustavi komponenti
        
    section Koncepti game enginea (1 tjedan)
        Razumijevanje okvira: Sustavi entiteta i komponenti
                            : Grafikoni scena
                            : Pipeline za resurse
                            : Profiliranje performansi
        
    section Vještine produkcije (1 mjesec)
        Profesionalni razvoj: Organizacija koda
                            : Suradnja u timu
                            : Strategije testiranja
                            : Optimizacija postavljanja
Loading

🛠️ Sažetak alata za razvoj tvoje igre

Nakon završetka ove lekcije, svladao si:

  • Principi animacije: Kretanje na temelju frameova i glatki prijelazi
  • Programiranje vođeno događajima: Rukovanje unosom tipkovnice s pravilnim upravljanjem događajima
  • Objektno orijentirani dizajn: Nasljedne hijerarhije i polimorfna sučelja
  • Obrasci komunikacije: Pub/sub arhitektura za održiv kod
  • Arhitektura petlje igre: Ciklusi ažuriranja i renderiranja u stvarnom vremenu
  • Sustavi unosa: Mapiranje korisničke kontrole s onemogućavanjem default ponašanja
  • Upravljanje resursima: Učitavanje spriteova i učinkovite tehnike renderiranja

Što možeš napraviti u sljedećih 5 minuta

  • Otvori konzolu preglednika i isprobaj addEventListener('keydown', console.log) da vidiš događaje tipkovnice
  • Kreiraj jednostavan div element i pomakni ga pomoću strelica
  • Eksperimentiraj s setInterval za kontinuirano kretanje
  • Pokušaj spriječiti default ponašanje pomoću event.preventDefault()

🎯 Što možeš postići ovaj sat

  • Završiti kviz poslije lekcije i razumjeti programiranje vođeno događajima
  • Izgraditi pokretnog heroja svemirskog broda s potpunim tipkovničkim upravljanjem
  • Implementirati glatke obrasce kretanja neprijatelja
  • Dodati granice koje sprječavaju izlazak objekata igre s ekrana
  • Izraditi osnovnu detekciju sudara između objekata igre

📅 Tvoj tjedni put prema savršenstvu animacije

  • Završiti kompletnu svemirsku igru s poliranim kretanjem i interakcijama
  • Dodati napredne obrasce kretanja poput krivulja, ubrzanja i fizike
  • Implementirati glatke prijelaze i funkcije easinga
  • Kreirati čestićne efekte i sustave vizualne povratne informacije
  • Optimizirati performanse igre za glatku igru na 60 fps
  • Dodati upravljanje dodirom za mobilne uređaje i responzivni dizajn

🌟 Tvoj mjesečni interaktivni razvoj

  • Izgraditi složene interaktivne aplikacije s naprednim sustavima animacije
  • Naučiti animacijske biblioteke poput GSAP-a ili stvoriti vlastiti animacijski motor
  • Doprinijeti open source projektima razvoja igara i animacije
  • Savladati optimizaciju performansi za grafički zahtjevne aplikacije
  • Kreirati edukativni sadržaj o razvoju igara i animaciji
  • Izgraditi portfelj koji prikazuje napredne vještine interaktivnog programiranja

Primjene u stvarnom svijetu: Tvoje vještine animacije igre direktno se primjenjuju na:

  • Interaktivne web aplikacije: Dinamičke nadzorne ploče i sučelja u realnom vremenu
  • Vizualizaciju podataka: Animirani grafikoni i interaktivna grafika
  • Edukacijski softver: Interaktivne simulacije i alati za učenje
  • Mobilni razvoj: Igračke upravljane dodirom i gestama
  • Desktop aplikacije: Electron aplikacije s glatkim animacijama
  • Web animacije: CSS i JavaScript animacijske biblioteke

Profesionalne vještine koje si stekao: Sada možeš:

  • Arhitektirati sustave vođene događajima koji skaliraju s kompleksnošću
  • Implementirati glatke animacije koristeći matematičke principe
  • Debugirati složene interakcijske sustave koristeći alate za razvoj preglednika
  • Optimizirati performanse igre za različite uređaje i preglednike
  • Dizajnirati održive strukture koda koristeći dokazane obrasce

Koncepti razvoja igara koje si svladao:

  • Upravljanje frekvencijom frameova: Razumijevanje FPS-a i kontrola vremena
  • Rukovanje unosom: Višekanalni tipkovnički i event sustavi
  • Životni ciklus objekata: Obrasci stvaranja, ažuriranja i uništenja
  • Sinkronizacija stanja: Održavanje konzistentnog stanja igre kroz frameove
  • Arhitektura događaja: Nepovezana komunikacija između sustava igre

Sljedeća razina: Spreman si dodati detekciju sudara, sustave bodovanja, zvučne efekte ili istražiti suvremene frameworkove za igre poput Phaser-a ili Three.js!

🌟 Postignuće otključano: Izgradio si kompletan interaktivni sustav igre s profesionalnim obrascima arhitekture!

Zadatak

Komentiraj svoj kod


Odricanje od odgovornosti: Ovaj je dokument preveden korištenjem AI usluge za prevođenje Co-op Translator. Iako težimo točnosti, imajte na umu da automatski prijevodi mogu sadržavati pogreške ili netočnosti. Izvorni dokument na izvornom jeziku smatra se autoritativnim izvorom. Za važne informacije preporučuje se stručni ljudski prijevod. Nismo odgovorni za bilo kakva nesporazuma ili pogrešna tumačenja koja proizlaze iz upotrebe ovog prijevoda.