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/uk/6-space-game/1-introduction
leestott a2fda673a6
🌐 Update translations via Co-op Translator
1 week ago
..
README.md 🌐 Update translations via Co-op Translator 1 week ago
assignment.md 🌐 Update translations via Co-op Translator 1 week ago

README.md

Створення космічної гри Частина 1: Вступ

video

Тест перед лекцією

Тест перед лекцією

Наслідування та композиція у розробці ігор

У попередніх уроках не було великої потреби турбуватися про архітектуру додатків, які ви створювали, оскільки проєкти були невеликими за масштабом. Однак, коли ваші додатки зростають у розмірах і складності, архітектурні рішення стають важливішими. Існує два основних підходи до створення великих додатків у 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. Ми слухаємо це повідомлення та переміщуємо hero як результат. Сила цього шаблону полягає в тому, що обробник подій і герой не знають один про одного. Ви можете переназначити ArrowLeft на клавішу A. Крім того, можна зробити щось зовсім інше на ArrowLeft, внісши кілька змін до функції on об'єкта eventEmitter:

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

Коли ваша гра стає складнішою, цей шаблон залишається незмінним у своїй складності, а ваш код залишається чистим. Дуже рекомендується використовувати цей шаблон.


🚀 Виклик

Подумайте, як шаблон pub-sub може покращити гру. Які частини повинні надсилати події, і як гра повинна на них реагувати? Зараз у вас є шанс проявити творчість, придумуючи нову гру та те, як її частини можуть поводитися.

Тест після лекції

Тест після лекції

Огляд і самостійне навчання

Дізнайтеся більше про Pub/Sub, прочитавши про це.

Завдання

Створіть макет гри


Відмова від відповідальності:
Цей документ був перекладений за допомогою сервісу автоматичного перекладу Co-op Translator. Хоча ми прагнемо до точності, будь ласка, майте на увазі, що автоматичні переклади можуть містити помилки або неточності. Оригінальний документ на його рідній мові слід вважати авторитетним джерелом. Для критичної інформації рекомендується професійний людський переклад. Ми не несемо відповідальності за будь-які непорозуміння або неправильні тлумачення, що виникають внаслідок використання цього перекладу.