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/sl/6-space-game/1-introduction/README.md

8.8 KiB

Izdelava vesoljske igre, 1. del: Uvod

video

Predhodni kviz

Predhodni kviz

Dedovanje in kompozicija pri razvoju iger

V prejšnjih lekcijah ni bilo veliko potrebe po skrbi za arhitekturo aplikacij, ki ste jih ustvarili, saj so bili projekti zelo majhnega obsega. Ko pa vaše aplikacije rastejo v velikosti in obsegu, postanejo arhitekturne odločitve pomembnejše. Obstajata dva glavna pristopa k ustvarjanju večjih aplikacij v JavaScriptu: kompozicija ali dedovanje. Obe imata svoje prednosti in slabosti, vendar ju bomo razložili v kontekstu igre.

Ena najbolj znanih knjig o programiranju je povezana z oblikovalskimi vzorci.

V igri imate objekte igre, ki so objekti, ki obstajajo na zaslonu. To pomeni, da imajo lokacijo v kartezijskem koordinatnem sistemu, opredeljeno z x in y koordinato. Ko razvijate igro, boste opazili, da imajo vsi vaši objekti igre standardne lastnosti, skupne za vsako igro, ki jo ustvarite, in sicer elemente, ki so:

  • lokacijsko osnovani Večina, če ne vsi, elementi igre temeljijo na lokaciji. To pomeni, da imajo lokacijo, x in y.
  • premični To so objekti, ki se lahko premaknejo na novo lokacijo. To je običajno junak, pošast ali NPC (ne-igralni lik), ne pa na primer statični objekt, kot je drevo.
  • samouničujoči Ti objekti obstajajo le določen čas, preden se pripravijo na brisanje. Običajno je to predstavljeno z logično vrednostjo mrtvo ali uničeno, ki signalizira igralnemu pogonu, da tega objekta ni več treba prikazovati.
  • časovno omejeni 'Časovna omejitev' je tipična lastnost kratkotrajnih objektov. Tipičen primer je kos besedila ali grafični učinek, kot je eksplozija, ki naj bo viden le nekaj milisekund.

Pomislite na igro, kot je Pac-Man. Ali lahko prepoznate štiri zgoraj navedene tipe objektov v tej igri?

Izražanje vedenja

Vse, kar smo opisali zgoraj, so vedenja, ki jih lahko imajo objekti igre. Kako jih torej kodiramo? To vedenje lahko izrazimo kot metode, povezane bodisi s klasami bodisi z objekti.

Klase

Ideja je uporabiti klase v kombinaciji z dedovanjem, da dodamo določeno vedenje klasi.

Dedovanje je pomemben koncept za razumevanje. Več o tem preberite v članku MDN o dedovanju.

V kodi je objekt igre običajno videti takole:


//set up the class GameObject
class GameObject {
  constructor(x, y, type) {
    this.x = x;
    this.y = y;
    this.type = type;
  }
}

//this class will extend the GameObject's inherent class properties
class Movable extends GameObject {
  constructor(x,y, type) {
    super(x,y, type)
  }

//this movable object can be moved on the screen
  moveTo(x, y) {
    this.x = x;
    this.y = y;
  }
}

//this is a specific class that extends the Movable class, so it can take advantage of all the properties that it inherits
class Hero extends Movable {
  constructor(x,y) {
    super(x,y, 'Hero')
  }
}

//this class, on the other hand, only inherits the GameObject properties
class Tree extends GameObject {
  constructor(x,y) {
    super(x,y, 'Tree')
  }
}

//a hero can move...
const hero = new Hero();
hero.moveTo(5,5);

//but a tree cannot
const tree = new Tree();

Vzemite si nekaj minut in si zamislite junaka iz Pac-Mana (na primer Inky, Pinky ali Blinky) ter kako bi bil napisan v JavaScriptu.

Kompozicija

Drugačen način obravnave dedovanja objektov je uporaba kompozicije. Takrat objekti izražajo svoje vedenje takole:

//create a constant gameObject
const gameObject = {
  x: 0,
  y: 0,
  type: ''
};

//...and a constant movable
const movable = {
  moveTo(x, y) {
    this.x = x;
    this.y = y;
  }
}
//then the constant movableObject is composed of the gameObject and movable constants
const movableObject = {...gameObject, ...movable};

//then create a function to create a new Hero who inherits the movableObject properties
function createHero(x, y) {
  return {
    ...movableObject,
    x,
    y,
    type: 'Hero'
  }
}
//...and a static object that inherits only the gameObject properties
function createStatic(x, y, type) {
  return {
    ...gameObject
    x,
    y,
    type
  }
}
//create the hero and move it
const hero = createHero(10,10);
hero.moveTo(5,5);
//and create a static tree which only stands around
const tree = createStatic(0,0, 'Tree'); 

Kateri vzorec naj uporabim?

Odločitev je vaša, kateri vzorec boste izbrali. JavaScript podpira oba pristopa.

--

Drug pogost vzorec pri razvoju iger obravnava problem upravljanja uporabniške izkušnje in zmogljivosti igre.

Pub/sub vzorec

Pub/Sub pomeni 'objavi-naroči se'

Ta vzorec obravnava idejo, da si različni deli vaše aplikacije ne bi smeli medsebojno poznati. Zakaj? To omogoča lažji pregled nad dogajanjem na splošno, če so različni deli ločeni. Prav tako omogoča enostavno spremembo vedenja, če je to potrebno. Kako to dosežemo? Z vzpostavitvijo nekaterih konceptov:

  • sporočilo: Sporočilo je običajno besedilni niz, ki ga spremlja neobvezna vsebina (kos podatkov, ki pojasnjuje, kaj sporočilo pomeni). Tipično sporočilo v igri je lahko KEY_PRESSED_ENTER.
  • objavljalec: Ta element objavi sporočilo in ga pošlje vsem naročnikom.
  • naročnik: Ta element posluša določena sporočila in izvede neko nalogo kot rezultat prejetega sporočila, na primer izstreli laser.

Implementacija je zelo majhna, vendar je to zelo močan vzorec. Tukaj je, kako ga lahko implementiramo:

//set up an EventEmitter class that contains listeners
class EventEmitter {
  constructor() {
    this.listeners = {};
  }
//when a message is received, let the listener to handle its payload
  on(message, listener) {
    if (!this.listeners[message]) {
      this.listeners[message] = [];
    }
    this.listeners[message].push(listener);
  }
//when a message is sent, send it to a listener with some payload
  emit(message, payload = null) {
    if (this.listeners[message]) {
      this.listeners[message].forEach(l => l(message, payload))
    }
  }
}

Za uporabo zgornje kode lahko ustvarimo zelo majhno implementacijo:

//set up a message structure
const Messages = {
  HERO_MOVE_LEFT: 'HERO_MOVE_LEFT'
};
//invoke the eventEmitter you set up above
const eventEmitter = new EventEmitter();
//set up a hero
const hero = createHero(0,0);
//let the eventEmitter know to watch for messages pertaining to the hero moving left, and act on it
eventEmitter.on(Messages.HERO_MOVE_LEFT, () => {
  hero.move(5,0);
});

//set up the window to listen for the keyup event, specifically if the left arrow is hit, emit a message to move the hero left
window.addEventListener('keyup', (evt) => {
  if (evt.key === 'ArrowLeft') {
    eventEmitter.emit(Messages.HERO_MOVE_LEFT)
  }
});

Zgoraj povežemo dogodek tipkovnice, ArrowLeft, in pošljemo sporočilo HERO_MOVE_LEFT. Poslušamo to sporočilo in premaknemo junaka kot rezultat. Prednost tega vzorca je, da poslušalec dogodkov in junak ne poznata drug drugega. Lahko premapirate ArrowLeft na tipko A. Poleg tega bi bilo mogoče narediti nekaj povsem drugega na ArrowLeft z nekaj spremembami funkcije on v eventEmitterju:

eventEmitter.on(Messages.HERO_MOVE_LEFT, () => {
  hero.move(5,0);
});

Ko se stvari zapletejo, ko vaša igra raste, ta vzorec ostane enako zapleten, vaša koda pa ostane čista. Zelo priporočljivo je, da sprejmete ta vzorec.


🚀 Izziv

Razmislite, kako lahko pub-sub vzorec izboljša igro. Kateri deli naj oddajajo dogodke in kako naj igra nanje reagira? Zdaj imate priložnost, da postanete kreativni in razmislite o novi igri ter kako bi se njeni deli obnašali.

Zaključni kviz

Zaključni kviz

Pregled in samostojno učenje

Več o Pub/Sub vzorcu preberite tukaj.

Naloga

Ustvarite osnutek igre


Omejitev odgovornosti:
Ta dokument je bil preveden z uporabo storitve za strojno prevajanje Co-op Translator. Čeprav si prizadevamo za natančnost, vas prosimo, da upoštevate, da lahko avtomatizirani prevodi vsebujejo napake ali netočnosti. Izvirni dokument v njegovem maternem jeziku je treba obravnavati kot avtoritativni vir. Za ključne informacije priporočamo profesionalni človeški prevod. Ne prevzemamo odgovornosti za morebitne nesporazume ali napačne razlage, ki izhajajo iz uporabe tega prevoda.