Hrvatski

Sveobuhvatan vodič za razvoj 2D igara s HTML5 Canvasom, pokrivajući postavljanje, osnovne koncepte, optimizaciju i napredne tehnike.

HTML5 Canvas: Vaš ulaz u svijet razvoja 2D igara

HTML5 Canvas element pruža moćnu i svestranu platformu za izradu 2D igara izravno unutar web preglednika. To ga čini dostupnim širokoj publici bez potrebe za dodacima ili preuzimanjima. Ovaj sveobuhvatni vodič provest će vas kroz osnove razvoja igara s HTML5 Canvasom, pokrivajući sve od osnovnog postavljanja do naprednih tehnika za stvaranje zanimljivih i performansnih igara.

Zašto odabrati HTML5 Canvas za razvoj 2D igara?

HTML5 Canvas nudi nekoliko prednosti za razvoj 2D igara:

Postavljanje razvojnog okruženja

Da biste započeli s razvojem igara pomoću HTML5 Canvasa, trebat će vam:

Ovdje je osnovna HTML datoteka za postavljanje vašeg Canvasa:


<!DOCTYPE html>
<html>
<head>
  <title>Moja prva Canvas igra</title>
  <style>
    body { margin: 0; }
    canvas { background: #eee; display: block; margin: 0 auto; }
  </style>
</head>
<body>
  <canvas id="gameCanvas" width="640" height="480"></canvas>
  <script>
    const canvas = document.getElementById('gameCanvas');
    const ctx = canvas.getContext('2d');

    // Ovdje će ići kod vaše igre
  </script>
</body>
</html>

Ovaj kod stvara Canvas element s ID-jem "gameCanvas" i postavlja njegovu širinu i visinu. Također dohvaća 2D kontekst za renderiranje, koji se koristi za crtanje na Canvasu.

Osnovni koncepti razvoja igara s HTML5 Canvasom

Petlja igre (Game Loop)

Petlja igre je srce svake igre. To je kontinuirani ciklus koji ažurira stanje igre, iscrtava grafiku igre i obrađuje korisnički unos. Tipična petlja igre izgleda ovako:


function gameLoop() {
  update();
  render();
  requestAnimationFrame(gameLoop);
}

function update() {
  // Ažuriraj logiku igre (npr. pozicija igrača, AI neprijatelja)
}

function render() {
  // Očisti platno
  ctx.clearRect(0, 0, canvas.width, canvas.height);

  // Iscrtaj elemente igre (npr. igrač, neprijatelji, pozadina)
}

requestAnimationFrame(gameLoop);

requestAnimationFrame je API preglednika koji zakazuje pozivanje funkcije prije sljedećeg iscrtavanja. To osigurava glatku i učinkovitu animaciju.

Crtanje oblika i slika

Canvas API pruža metode za crtanje raznih oblika, uključujući pravokutnike, krugove i linije. Također vam omogućuje crtanje slika na Canvasu.

Crtanje pravokutnika


ctx.fillStyle = 'red'; // Postavi boju ispune
ctx.fillRect(10, 10, 50, 50); // Iscrtaj ispunjeni pravokutnik na (10, 10) širine 50 i visine 50

ctx.strokeStyle = 'blue'; // Postavi boju obruba
ctx.strokeRect(70, 10, 50, 50); // Iscrtaj obris pravokutnika na (70, 10) širine 50 i visine 50

Crtanje kruga


ctx.beginPath();
ctx.arc(150, 35, 25, 0, 2 * Math.PI); // Iscrtaj krug na (150, 35) s radijusom 25
ctx.fillStyle = 'green';
ctx.fill();
ctx.closePath();

Crtanje slike


const image = new Image();
image.src = 'path/to/your/image.png';

image.onload = function() {
  ctx.drawImage(image, 200, 10); // Iscrtaj sliku na (200, 10)
};

Rukovanje korisničkim unosom

Kako bi vaša igra bila interaktivna, morate obrađivati korisnički unos, kao što su pritisci tipki, klikovi mišem i događaji dodira. Možete koristiti JavaScriptove slušače događaja (event listeners) za otkrivanje tih događaja.

Unos s tipkovnice


document.addEventListener('keydown', function(event) {
  if (event.key === 'ArrowLeft') {
    // Pomakni igrača lijevo
  }
  if (event.key === 'ArrowRight') {
    // Pomakni igrača desno
  }
});

Unos mišem


canvas.addEventListener('mousedown', function(event) {
  const x = event.clientX - canvas.offsetLeft;
  const y = event.clientY - canvas.offsetTop;

  // Provjeri je li se klik dogodio unutar određenog područja
});

Detekcija sudara

Detekcija sudara je proces utvrđivanja kada se dva objekta u igri preklapaju ili sijeku. Ovo je ključno za mnoge mehanike igre, kao što su sudari igrača s neprijateljima ili udarci projektila.

Jednostavna detekcija sudara pravokutnika


function checkCollision(rect1, rect2) {
  return (
    rect1.x < rect2.x + rect2.width &&
    rect1.x + rect1.width > rect2.x &&
    rect1.y < rect2.y + rect2.height &&
    rect1.y + rect1.height > rect2.y
  );
}

// Primjer korištenja:
const player = { x: 10, y: 10, width: 32, height: 32 };
const enemy = { x: 100, y: 100, width: 32, height: 32 };

if (checkCollision(player, enemy)) {
  // Sudar detektiran!
}

Animacija sprajtova (Sprite Animation)

Animacija sprajtova je tehnika koja se koristi za stvaranje iluzije pokreta brzim prikazivanjem niza slika (sprajtova). Svaka slika predstavlja različit okvir animacije.

Za implementaciju animacije sprajtova, trebat će vam sprite sheet, što je jedna slika koja sadrži sve okvire animacije. Zatim možete koristiti metodu drawImage za crtanje određenih okvira iz sprite sheeta na Canvas.


const spriteSheet = new Image();
spriteSheet.src = 'path/to/your/sprite-sheet.png';

const frameWidth = 32; // Širina svakog okvira
const frameHeight = 32; // Visina svakog okvira
let currentFrame = 0; // Indeks trenutnog okvira

function animate() {
  // Izračunaj x i y koordinate trenutnog okvira u sprite sheetu
  const spriteX = currentFrame * frameWidth;
  const spriteY = 0; // Pretpostavljajući da su svi okviri u jednom redu

  // Iscrtaj trenutni okvir na Canvas
  ctx.drawImage(
    spriteSheet,
    spriteX,
    spriteY,
    frameWidth,
    frameHeight,
    100, // x koordinata na platnu
    100, // y koordinata na platnu
    frameWidth,
    frameHeight
  );

  // Povećaj indeks trenutnog okvira
  currentFrame = (currentFrame + 1) % numberOfFrames; // numberOfFrames je ukupan broj okvira u animaciji
}

Napredne tehnike i optimizacija

Stanja igre

Upravljanje različitim stanjima igre (npr. izbornik, igra, pauza, kraj igre) ključno je za organizaciju logike vaše igre. Možete koristiti jednostavan stroj stanja (state machine) za upravljanje tim stanjima.


let gameState = 'menu'; // Početno stanje igre

function update() {
  switch (gameState) {
    case 'menu':
      updateMenu();
      break;
    case 'game':
      updateGame();
      break;
    case 'pause':
      updatePause();
      break;
    case 'gameover':
      updateGameOver();
      break;
  }
}

function render() {
  // Očisti platno
  ctx.clearRect(0, 0, canvas.width, canvas.height);

  switch (gameState) {
    case 'menu':
      renderMenu();
      break;
    case 'game':
      renderGame();
      break;
    case 'pause':
      renderPause();
      break;
    case 'gameover':
      renderGameOver();
      break;
  }
}

Spremišta objekata (Object Pools)

Često stvaranje i uništavanje objekata može biti računski skupo. Spremišta objekata pružaju način ponovnog korištenja objekata umjesto stvaranja novih. To može značajno poboljšati performanse, posebno za igre s mnogo dinamički stvorenih objekata, poput projektila.


function createObjectPool(size, objectFactory) {
  const pool = [];

  for (let i = 0; i < size; i++) {
    pool.push(objectFactory());
  }

  return {
    get: function() {
      if (pool.length > 0) {
        return pool.pop();
      } else {
        // Opcionalno stvori novi objekt ako je spremište prazno
        return objectFactory();
      }
    },
    release: function(object) {
      pool.push(object);
    }
  };
}

// Primjer korištenja:
function createBullet() {
  return { x: 0, y: 0, speed: 10, active: false };
}

const bulletPool = createObjectPool(100, createBullet);

Mape pločica (Tile Maps)

Mape pločica su uobičajena tehnika za stvaranje svjetova igara. Mapa pločica je mreža pločica, gdje svaka pločica predstavlja malu sliku ili uzorak. Mape pločica su učinkovite za stvaranje velikih i detaljnih okruženja igre.

Za implementaciju mapa pločica, trebat će vam tile sheet, koji sadrži sve pojedinačne pločice. Također će vam trebati podatkovna struktura koja definira raspored mape pločica. Ta podatkovna struktura može biti jednostavna 2D matrica.


const tileSheet = new Image();
tileSheet.src = 'path/to/your/tile-sheet.png';

const tileWidth = 32;
const tileHeight = 32;

const mapData = [
  [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
  [0, 1, 1, 1, 1, 1, 1, 1, 1, 0],
  [0, 1, 0, 0, 0, 0, 0, 0, 1, 0],
  [0, 1, 0, 0, 0, 0, 0, 0, 1, 0],
  [0, 1, 1, 1, 1, 1, 1, 1, 1, 0],
  [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
];

function drawTileMap() {
  for (let row = 0; row < mapData.length; row++) {
    for (let col = 0; col < mapData[row].length; col++) {
      const tileIndex = mapData[row][col];

      // Izračunaj x i y koordinate pločice u tile sheetu
      const spriteX = (tileIndex % numberOfTilesPerRow) * tileWidth; // numberOfTilesPerRow je broj pločica u svakom redu tile sheeta
      const spriteY = Math.floor(tileIndex / numberOfTilesPerRow) * tileHeight;

      // Iscrtaj pločicu na Canvas
      ctx.drawImage(
        tileSheet,
        spriteX,
        spriteY,
        tileWidth,
        tileHeight,
        col * tileWidth, // x koordinata na platnu
        row * tileHeight, // y koordinata na platnu
        tileWidth,
        tileHeight
      );
    }
  }
}

Optimizacija performansi

Optimiziranje vaše Canvas igre ključno je za postizanje glatkih i responzivnih performansi, posebno na slabijim uređajima.

Korisne biblioteke i okviri

Nekoliko JavaScript biblioteka i okvira može pojednostaviti razvoj igara s HTML5 Canvasom:

Primjeri igara napravljenih s HTML5 Canvasom

Mnoge popularne i uspješne igre izgrađene su pomoću HTML5 Canvasa, pokazujući njegove mogućnosti:

Zaključak

HTML5 Canvas je moćna i dostupna platforma za razvoj 2D igara. Sa svojom kompatibilnošću na više platformi, otvorenim standardima i velikom zajednicom, Canvas pruža čvrst temelj za stvaranje zanimljivih i performansnih igara. Ovladavanjem osnovnim konceptima i naprednim tehnikama o kojima se govori u ovom vodiču, možete otključati puni potencijal HTML5 Canvasa i oživjeti svoje ideje za igre.

Ne zaboravite istražiti dostupne biblioteke i okvire kako biste dodatno pojednostavili svoj proces razvoja i iskoristili unaprijed izgrađene funkcionalnosti. Sretno na vašem putu razvoja igara!