|
1 week ago | |
---|---|---|
.. | ||
README.md | 1 week ago | |
assignment.md | 1 week ago |
README.md
Изградња свемирске игре, део 1: Увод
Квиз пре предавања
Наслеђивање и композиција у развоју игара
У претходним лекцијама није било потребе да се превише бринете о дизајну архитектуре апликација које сте правили, јер су пројекти били веома малог обима. Међутим, када ваше апликације почну да расту у величини и обиму, архитектонске одлуке постају важније. Постоје два главна приступа за креирање већих апликација у JavaScript-у: композиција или наслеђивање. Оба приступа имају своје предности и мане, али хајде да их објаснимо у контексту игре.
✅ Једна од најпознатијих књига о програмирању односи се на шаблоне дизајна.
У игри имате објекте игре
, који су објекти који постоје на екрану. То значи да имају локацију у картезијанском координатном систему, коју карактеришу x
и y
координате. Како развијате игру, приметићете да сви ваши објекти игре имају стандардна својства, заједничка за сваку игру коју креирате, а то су елементи који су:
- засновани на локацији Већина, ако не и сви, елементи игре су засновани на локацији. То значи да имају локацију,
x
иy
. - покретни Ово су објекти који могу да се померају на нову локацију. То је обично херој, чудовиште или NPC (неконтролисани лик), али не, на пример, статичан објекат као што је дрво.
- самоуништавајући Ови објекти постоје само одређено време пре него што се припреме за брисање. Обично је то представљено
dead
илиdestroyed
булеаном који сигнализира игри да овај објекат више не треба да се приказује. - са периодом хлађења 'Период хлађења' је типично својство краткотрајних објеката. Типичан пример је комад текста или графички ефекат попут експлозије који треба да се види само неколико милисекунди.
✅ Размислите о игри као што је Pac-Man. Можете ли идентификовати четири горе наведене врсте објеката у овој игри?
Изражавање понашања
Све што смо горе описали представља понашање које објекти игре могу имати. Како то можемо кодирати? Ово понашање можемо изразити као методе повезане са класама или објектима.
Класе
Идеја је да се користе класе
у комбинацији са наслеђивањем
како би се одређено понашање додало класи.
✅ Наслеђивање је важан концепт за разумевање. Сазнајте више у чланку о наслеђивању на MDN-у.
Изражено кроз код, објекат игре обично изгледа овако:
//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();
✅ Одвојите неколико минута да замислите хероја из Pac-Man-а (на пример, Inky, Pinky или Blinky) и како би био написан у JavaScript-у.
Композиција
Други начин руковања наслеђивањем објеката је коришћењем композиције. Тада објекти изражавају своје понашање на следећи начин:
//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');
Који шаблон треба да користим?
На вама је да одлучите који шаблон ћете користити. JavaScript подржава оба ова парадигме.
--
Још један шаблон који је чест у развоју игара бави се проблемом управљања корисничким искуством и перформансама игре.
Pub/sub шаблон
✅ Pub/Sub означава 'publish-subscribe' (објави-претплати се)
Овај шаблон се бави идејом да различити делови ваше апликације не би требало да знају једни за друге. Зашто је то важно? Олакшава разумевање шта се генерално дешава ако су различити делови раздвојени. Такође олакшава изненадну промену понашања ако је то потребно. Како то постижемо? Успостављамо неке концепте:
- порука: Порука је обично текстуални низ праћен опционим подацима (комадом података који појашњава о чему се ради у поруци). Типична порука у игри може бити
KEY_PRESSED_ENTER
. - издавач: Овај елемент објављује поруку и шаље је свим претплатницима.
- претплатник: Овај елемент слуша одређене поруке и извршава неки задатак као резултат примања те поруке, као што је испаљивање ласера.
Имплементација је прилично мала по величини, али је веома моћан шаблон. Ево како може бити имплементиран:
//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))
}
}
}
Да бисмо користили горњи код, можемо направити веома малу имплементацију:
//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)
}
});
Горе повезујемо догађај са тастатуре, ArrowLeft
, и шаљемо поруку HERO_MOVE_LEFT
. Слушамо ту поруку и као резултат померамо хероја
. Снага овог шаблона је у томе што слушач догађаја и херој не знају један за другог. Можете преповезати ArrowLeft
на тастер A
. Поред тога, могуће је урадити нешто потпуно другачије на ArrowLeft
прављењем неколико измена у функцији on
објекта eventEmitter:
eventEmitter.on(Messages.HERO_MOVE_LEFT, () => {
hero.move(5,0);
});
Како игра постаје сложенија, овај шаблон остаје исте сложености, а ваш код остаје чист. Препоручује се усвајање овог шаблона.
🚀 Изазов
Размислите о томе како Pub/Sub шаблон може побољшати игру. Који делови би требало да емитују догађаје, а како би игра требало да реагује на њих? Сада је ваша шанса да будете креативни и размислите о новој игри и како би њени делови могли да се понашају.
Квиз после предавања
Преглед и самостално учење
Сазнајте више о Pub/Sub шаблону читајући о њему.
Задатак
Одрицање од одговорности:
Овај документ је преведен коришћењем услуге за превођење помоћу вештачке интелигенције Co-op Translator. Иако настојимо да обезбедимо тачност, молимо вас да имате у виду да аутоматски преводи могу садржати грешке или нетачности. Оригинални документ на изворном језику треба сматрати ауторитативним извором. За критичне информације препоручује се професионални превод од стране људи. Не сносимо одговорност за било каква неспоразумевања или погрешна тумачења настала услед коришћења овог превода.