Если вы никогда не сталкивались и не углублялись в область настраиваемых клавиатур, быстрый поиск в Google по запросу «горячая замена» покажет вам, что «клавиатура с возможностью горячей замены позволяет менять переключатели только с помощью съемник переключателя, так что вы буквально просто вытаскиваете переключатели и подключаете другие; это легко." По сути, каждый переключатель клавиатуры — это элемент под колпачками клавиш, который фактически регистрирует ввод на клавиатуре, но я отвлекся.

Так какое это имеет отношение к разработке игр? Ну, на самом деле ничего. Однако это дает нам хорошую аналогию с шаблоном проектирования, который мы обсудим в этой статье. Но прежде чем мы начнем, давайте сначала обсудим более вопиющий вопрос: зачем использовать шаблоны проектирования?

Изменение кода

Как бы мы, разработчики, не хотели бы просто добавлять или изменять существующий код — будь то добавление новой функции, исправление ошибки или небольшой рефакторинг, вы должны сначала понять, что делает существующий код. Вам нужно иметь общее представление о том, где вы хотели бы внести изменения и какие области они могут или не могут повлиять на остальную часть программы. Кроме того, если изменение кода не является незначительным, вам также потребуется выполнить небольшую очистку, чтобы следующий человек, которому нужно посмотреть код, не споткнулся о морщины, которые вы оставили в исходном коде.

Подводя итог, блок-схема будет выглядеть примерно так:

Однако вы можете не осознавать одну вещь: вы можете потратить столько же или даже больше времени, пытаясь понять код. В зависимости от того, насколько сильно связана программа, вам, возможно, придется пройти через множество обручей, прежде чем вы, наконец, сможете приступить к кодированию своего решения. Чтобы сократить время, затрачиваемое на изучение кода, мы можем структурировать код таким образом, чтобы свести к минимуму объем кода, который нам нужно понять, прежде чем можно будет добиться прогресса. Здесь на помощь приходят шаблоны проектирования.

Шаблоны проектирования

Шаблоны проектирования бывают разных форм и размеров. Некоторые сосредотачиваются на создании объектов, в то время как другие озабочены структурнойкомпозицией классов и объектов — они используют наследование для создания интерфейсов и определения способов компоновки объектов для получения новых функций. . Последний тип подпадает под поведенческие, которые конкретно связаны с общением между объектами. Тот, о котором я хотел бы поговорить сегодня, называется шаблоном проектирования «Команда», который относится к поведенческому типу.

Шаблон проектирования «Команда»

Я мог бы углубиться в детали и дать подробное объяснение того, что такое шаблон проектирования команд, но я думаю, что это еще больше запутает вас, поэтому давайте сразу перейдем к примеру. ПРИМЕЧАНИЕ.Синтаксис кода, написанного ниже, использует JavaScript ES6.

В каждой игре должен быть способ взаимодействия с игрой. Это может быть множество различных форм пользовательского ввода, таких как нажатие кнопок на контроллере, щелчки мышью, ввод с клавиатуры, и этот список можно продолжить. Эти входы связаны с некоторой функцией, которая обеспечивает действие в игре:

Простую кодовую реализацию приведенного выше примера можно представить так:

class InputHander {
  ...
  handleInput(event) => {
    if (event.target === BUTTON_X) {
      jump();  
    } else if (event.target === BUTTON_Y) {
      fireGun();
    } else if (event.target === BUTTON_A) {
      swapWeapon();
    } else if (event.target === BUTTON_B) {
      doABarrelRoll();
    }
  }
};

Это было бы хорошо, если бы кнопки были жестко закодированы для этих действий, но в настоящее время большинство игр позволяют пользователям изменять сопоставление своих элементов управления. Для их поддержки нам нужно переключить прямые вызовы действий (например, jump() и fireGun()) на что-то заменяемое. Введите: шаблон команды.

Сначала мы определяем базовый класс для представления команды триггера ввода для игры:

class Command {
  execute() => {
    throw new error("You have to implement this execute method");
  }
};

Затем создайте группу подклассов, реализующих триггерную команду для разных игровых действий:

class JumpCommand extends Command {
  execute() => {
    jump();
  }
};
class FireCommand extends Command {
  execute() => {
    fireGun();
  }
};
// You get the idea...

Вернемся к нашему обработчику ввода, мы можем установить команды для каждой кнопки:

class InputHandler {
  constructor() => {
    this._buttonX = null;
    this._buttonY = null;
    this._buttonA = null;
    this._buttonB = null;
  }
  mapButton(button, command) => {
    // code to compare which button to assign command
  }
  ...
};

Теперь обработчик ввода просто вызывает соответствующую команду выполнения:

class InputHandler {
  ...
  handleInput(event) => {
    if (event.target === BUTTON_X) { 
      this._buttonX.execute();
    } else if (event.target === BUTTON_Y) {
      this._buttonY.execute();
    } else if (event.target === BUTTON_A) {
      this._buttonA.execute();
    } else if (event.target === BUTTON_B) {
      this._buttonB.execute();
    }
  }
};

Каждому входу теперь косвенно назначается действие:

Это шаблон команды в двух словах.

Запуск его обратно

Таким образом, чтобы связать все вместе, шаблон проектирования «Команда» похож на переключатели с возможностью «горячей» замены на клавиатуре. Это обеспечивает гибкость для сопоставления пользовательского ввода с элементами управления игрой. Это также упрощает создание дополнительных команд, не затрагивая класс, обрабатывающий входные данные. Разработчики могут легко обратиться к некоторым примерам создания и назначения команд, а затем быстро приступить к добавлению или изменению поведения игры. Все это достигается без увязания в том, как это может повлиять на остальную часть кодовой базы.

Если вы хотите узнать больше, посетите следующие ссылки: