Lietuvių

Išsamus HTML5 drobės vadovas 2D žaidimų kūrimui, apimantis sąranką, pagrindines koncepcijas, optimizavimą ir pažangias technikas.

HTML5 drobė: jūsų vartai į 2D žaidimų kūrimą

HTML5 drobės (Canvas) elementas suteikia galingą ir universalią platformą kurti 2D žaidimus tiesiogiai interneto naršyklėje. Dėl to jie yra prieinami plačiajai auditorijai, nereikalaujant jokių papildinių ar atsisiuntimų. Šis išsamus vadovas supažindins jus su HTML5 drobės žaidimų kūrimo pagrindais, apimant viską nuo pradinės sąrankos iki pažangių technikų, skirtų kurti įtraukiančius ir našius žaidimus.

Kodėl verta rinktis HTML5 drobę 2D žaidimų kūrimui?

HTML5 drobė siūlo keletą privalumų kuriant 2D žaidimus:

Kūrimo aplinkos paruošimas

Norėdami pradėti kurti žaidimus su HTML5 drobe, jums reikės:

Štai pagrindinis HTML failas jūsų drobei paruošti:


<!DOCTYPE html>
<html>
<head>
  <title>Mano pirmasis drobės žaidimas</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');

    // Čia bus jūsų žaidimo kodas
  </script>
</body>
</html>

Šis kodas sukuria drobės elementą su ID "gameCanvas" ir nustato jo plotį bei aukštį. Taip pat jis gauna 2D atvaizdavimo kontekstą (rendering context), kuris naudojamas piešimui ant drobės.

Pagrindinės HTML5 drobės žaidimų kūrimo koncepcijos

Žaidimo ciklas

Žaidimo ciklas (game loop) yra bet kurio žaidimo šerdis. Tai nuolatinis ciklas, kuris atnaujina žaidimo būseną, atvaizduoja žaidimo grafiką ir apdoroja vartotojo įvestį. Tipiškas žaidimo ciklas atrodo taip:


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

function update() {
  // Atnaujinti žaidimo logiką (pvz., žaidėjo poziciją, priešų DI)
}

function render() {
  // Išvalyti drobę
  ctx.clearRect(0, 0, canvas.width, canvas.height);

  // Piešti žaidimo elementus (pvz., žaidėją, priešus, foną)
}

requestAnimationFrame(gameLoop);

requestAnimationFrame yra naršyklės API, kuri suplanuoja funkcijos iškvietimą prieš kitą ekrano perpiešimą. Tai užtikrina sklandžią ir efektyvią animaciją.

Figūrų ir paveikslėlių piešimas

Drobės API suteikia metodus įvairioms figūroms piešti, įskaitant stačiakampius, apskritimus ir linijas. Taip pat ji leidžia piešti paveikslėlius ant drobės.

Stačiakampio piešimas


ctx.fillStyle = 'red'; // Nustatyti užpildo spalvą
ctx.fillRect(10, 10, 50, 50); // Nupiešti užpildytą stačiakampį ties (10, 10), kurio plotis 50 ir aukštis 50

ctx.strokeStyle = 'blue'; // Nustatyti kontūro spalvą
ctx.strokeRect(70, 10, 50, 50); // Nupiešti stačiakampio kontūrą ties (70, 10), kurio plotis 50 ir aukštis 50

Apskritimo piešimas


ctx.beginPath();
ctx.arc(150, 35, 25, 0, 2 * Math.PI); // Nupiešti apskritimą ties (150, 35), kurio spindulys 25
ctx.fillStyle = 'green';
ctx.fill();
ctx.closePath();

Paveikslėlio piešimas


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

image.onload = function() {
  ctx.drawImage(image, 200, 10); // Nupiešti paveikslėlį ties (200, 10)
};

Vartotojo įvesties apdorojimas

Kad jūsų žaidimas būtų interaktyvus, turite apdoroti vartotojo įvestį, pavyzdžiui, klaviatūros paspaudimus, pelės paspaudimus ir lietimo įvykius. Galite naudoti JavaScript įvykių klausytojus (event listeners) šiems įvykiams aptikti.

Klaviatūros įvestis


document.addEventListener('keydown', function(event) {
  if (event.key === 'ArrowLeft') {
    // Judinti žaidėją į kairę
  }
  if (event.key === 'ArrowRight') {
    // Judinti žaidėją į dešinę
  }
});

Pelės įvestis


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

  // Patikrinti, ar paspaudimas įvyko tam tikroje srityje
});

Susidūrimų aptikimas

Susidūrimų aptikimas (collision detection) yra procesas, nustatantis, kada du žaidimo objektai persidengia arba susikerta. Tai yra būtina daugeliui žaidimo mechanikų, pavyzdžiui, žaidėjo ir priešo susidūrimams ar sviedinių pataikymams.

Paprastas stačiakampių susidūrimo aptikimas


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

// Naudojimo pavyzdys:
const player = { x: 10, y: 10, width: 32, height: 32 };
const enemy = { x: 100, y: 100, width: 32, height: 32 };

if (checkCollision(player, enemy)) {
  // Susidūrimas aptiktas!
}

Spraito animacija

Spraito animacija (sprite animation) yra technika, naudojama sukurti judesio iliuziją, greitai rodant paveikslėlių (spraitų) seką. Kiekvienas paveikslėlis atspindi skirtingą animacijos kadrą.

Norėdami įgyvendinti spraito animaciją, jums reikės spraitų lapo (sprite sheet) – vieno paveikslėlio, kuriame yra visi animacijos kadrai. Tuomet galite naudoti drawImage metodą, kad nupieštumėte konkrečius kadrus iš spraitų lapo ant drobės.


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

const frameWidth = 32; // Kiekvieno kadro plotis
const frameHeight = 32; // Kiekvieno kadro aukštis
let currentFrame = 0; // Dabartinio kadro indeksas

function animate() {
  // Apskaičiuoti dabartinio kadro x ir y koordinates spraitų lape
  const spriteX = currentFrame * frameWidth;
  const spriteY = 0; // Darome prielaidą, kad visi kadrai yra vienoje eilutėje

  // Nupiešti dabartinį kadrą ant drobės
  ctx.drawImage(
    spriteSheet,
    spriteX,
    spriteY,
    frameWidth,
    frameHeight,
    100, // x koordinatė ant drobės
    100, // y koordinatė ant drobės
    frameWidth,
    frameHeight
  );

  // Padidinti dabartinio kadro indeksą
  currentFrame = (currentFrame + 1) % numberOfFrames; // numberOfFrames yra bendras kadrų skaičius animacijoje
}

Pažangios technikos ir optimizavimas

Žaidimo būsenos

Skirtingų žaidimo būsenų (pvz., meniu, žaidimas, pauzė, žaidimo pabaiga) valdymas yra labai svarbus norint tvarkingai organizuoti žaidimo logiką. Šioms būsenoms valdyti galite naudoti paprastą būsenų mašiną (state machine).


let gameState = 'menu'; // Pradinė žaidimo būsena

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

function render() {
  // Išvalyti drobę
  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;
  }
}

Objektų telkiniai

Dažnas objektų kūrimas ir naikinimas gali būti brangus skaičiavimo požiūriu. Objektų telkiniai (object pools) suteikia būdą pakartotinai naudoti objektus, užuot kūrus naujus. Tai gali žymiai pagerinti našumą, ypač žaidimuose su daug dinamiškai kuriamų objektų, pavyzdžiui, sviedinių.


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 {
        // Pasirinktinai sukurti naują objektą, jei telkinys tuščias
        return objectFactory();
      }
    },
    release: function(object) {
      pool.push(object);
    }
  };
}

// Naudojimo pavyzdys:
function createBullet() {
  return { x: 0, y: 0, speed: 10, active: false };
}

const bulletPool = createObjectPool(100, createBullet);

Elementų žemėlapiai

Elementų žemėlapiai (tile maps) yra paplitusi technika žaidimų pasauliams kurti. Elementų žemėlapis yra tinklelis iš elementų, kur kiekvienas elementas atspindi mažą paveikslėlį ar raštą. Elementų žemėlapiai yra efektyvūs kuriant dideles ir detalias žaidimų aplinkas.

Norėdami įgyvendinti elementų žemėlapius, jums reikės elementų lapo (tile sheet), kuriame yra visi atskiri elementai. Taip pat jums reikės duomenų struktūros, kuri apibrėžia elementų žemėlapio išdėstymą. Ši duomenų struktūra gali būti paprastas dvimatis masyvas.


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];

      // Apskaičiuoti elemento x ir y koordinates elementų lape
      const spriteX = (tileIndex % numberOfTilesPerRow) * tileWidth; // numberOfTilesPerRow yra elementų skaičius kiekvienoje elementų lapo eilutėje
      const spriteY = Math.floor(tileIndex / numberOfTilesPerRow) * tileHeight;

      // Nupiešti elementą ant drobės
      ctx.drawImage(
        tileSheet,
        spriteX,
        spriteY,
        tileWidth,
        tileHeight,
        col * tileWidth, // x koordinatė ant drobės
        row * tileHeight, // y koordinatė ant drobės
        tileWidth,
        tileHeight
      );
    }
  }
}

Našumo optimizavimas

Drobės žaidimo optimizavimas yra labai svarbus norint pasiekti sklandų ir greitai reaguojantį našumą, ypač silpnesniuose įrenginiuose.

Naudingos bibliotekos ir karkasai

Keletas JavaScript bibliotekų ir karkasų gali supaprastinti HTML5 drobės žaidimų kūrimą:

HTML5 drobės žaidimų pavyzdžiai

Daugybė populiarių ir sėkmingų žaidimų buvo sukurti naudojant HTML5 drobę, demonstruojant jos galimybes:

Išvada

HTML5 drobė yra galinga ir prieinama platforma 2D žaidimų kūrimui. Dėl suderinamumo su įvairiomis platformomis, atvirų standartų ir didelės bendruomenės, drobė suteikia tvirtą pagrindą kurti įtraukiančius ir našius žaidimus. Įvaldę šiame vadove aptartas pagrindines koncepcijas ir pažangias technikas, galėsite išnaudoti visą HTML5 drobės potencialą ir paversti savo žaidimų idėjas realybe.

Nepamirškite išbandyti prieinamų bibliotekų ir karkasų, kad dar labiau supaprastintumėte savo kūrimo procesą ir pasinaudotumėte jau paruoštais funkcionalumais. Sėkmės jūsų žaidimų kūrimo kelionėje!