Глава IV в серии руководств о том, как создать игру с нуля с помощью TypeScript и собственных API-интерфейсов браузера.

Привет! Добро пожаловать в серию руководств о том, как создать простую пошаговую игру с нуля с помощью TypeScript! В этом руководстве мы используем только собственные API-интерфейсы браузера и постепенно добавляем новые функции благодаря принципам SOLID и общим шаблоны.

В предыдущем посте мы подготовили сцену для утилиты Ships: created Color и настроили слой foreground холста. Сегодня мы поговорим о духе товарищества и противодействии и представим трех новых членов нашей счастливой семьи: Team, Fleet и, конечно же, Ship.

В главе IV «Корабли» мы реализуем самый важный токен нашей пошаговой игры: мы рисуем Ships. Игроки будут использовать их для нападения на других игроков. Потеря всех кораблей означает проигрыш в игре. Вы можете найти другие главы этой серии здесь :

Смело переходите в ships-1 ветку репозитория. Он содержит рабочий результат предыдущих постов и является отличной отправной точкой для этого.

Оглавление

  1. Вступление
  2. Команда
  3. Ваш флот, капитан!
  4. Испытательный флот
  5. Первый Корабль
  6. Заключение

Команда

Многие игры так или иначе основаны на конфликте. Игрок борется за преодоление препятствий и проблем. Игрок работает с препятствиями окружающей среды, борется с ИИ и другими игроками, решает головоломки и загадки.

Когда мы думаем о командах, наша первая ассоциация, вероятно, - это «сотрудничество», «совместная работа». Но есть и другая сторона понятия «команда». Это оппозиция. Почему так? Разве это не противоположный термин? Ну и да, и нет. Люди объединяются в команду, чтобы что-то делать. Сотрудничать, работать вместе. Добиться результата быстрее / эффективнее / проще. Когда мы говорим об играх, команды сотрудничают, чтобы преодолеть конфликт. Они вместе играют против чего-то, может быть, даже другой команды.

С этой точки зрения мы можем думать о «команде» как о «стороне»: «моя сторона» против «их». Сколько людей на самом деле в команде, второстепенно. Важно противостояние: одна команда играет против другой.

В нашей довольно скромной игре у нас 2 команды, каждая из которых состоит только из одного игрока. Мы могли бы использовать понятие «игрок» и вообще не беспокоиться о «команде». Но кто знает, может быть, в будущем мы расширимся и позволим игрокам объединить свои силы под эгидой Команды? Давайте оставим наши варианты открытыми, обычно это хорошая стратегия.

Как мы будем называть наши команды? А как насчет «синих» и «красных»? Но что, если нам нужны разные цвета? Имея такое имя, мы непреднамеренно связываем логику с представлением. И это почти всегда плохая идея.

Может, тогда «Мой» против «Врага»? Где игрок очевидно в «Моей» команде, верно? Ну вот и проблема. Что, если мы введем мультиплеер в будущих итерациях, и все команды будут принадлежать реальным игрокам. Какой из них считать «Моим»?

Я предлагаю использовать очень общие названия: команда «A» против команды «B». Таким образом, мы не связываем название команды с какой-либо функциональностью. Команды будут представлять только одно: оппозицию.



Реализация может иметь множество форм, я остановлюсь на простом перечислении:

И напильник для него:

Конечная цель игры - потопить все корабли противника. Team A попытается потопить корабли, принадлежащие Team B. Поскольку у нас более одного корабля, имеет смысл создать какую-то структуру коллекции, которая обрабатывает массовые операции с ними. Назовем это Fleet.

Ваш флот, капитан!

Флот еще один Entity:

И по традиции не забываем о напильнике:

У каждой команды есть свой флот. Флот присваивается однажды созданной команде и никогда не меняется:

Примечание

Если eslint / IDE жалуются на неиспользованную переменную Team, значит, вы стали жертвой известной ошибки плагина eslint. Чтобы «исправить» это, вы можете отключить проверку для этой строки:

Или вы можете использовать псевдоним:

Я выберу первый подход, так как будет легче удалить эту строку, когда поступит соответствующее исправление.

Как и любой другой объект, Fleet должен найти свое место в иерархии. Давайте сделаем его прямым потомком игры:

Здесь мы создаем два флота, по одному для каждой команды. Затем мы добавляем их в массив игровых сущностей.

Испытательный флот

Мы должны обновить наши тесты, чтобы отразить эти изменения:

Все это должно выглядеть знакомо: мы просто следим за прототипом Fleet, поскольку у нас нет прямого доступа к экземпляру. Затем мы проверяем, что Awake и Update вызываются только после вызова соответствующих методов Game.

Потрясающие! Как и любой другой Entity, мы должны протестировать Fleet. Сейчас он почти пуст, так что давайте проверим, по крайней мере, мы не нарушаем родительскую функциональность: мы по-прежнему правильно Awake и Update компоненты:

Подход такой же, как и для всех других сущностей: мы создаем поддельные компоненты, присоединяем их к Fleet, выполняем Awake и Update, чтобы увидеть, действительно ли компоненты были активированы и обновлены:

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

И обновите бочку, чтобы отразить это изменение:

Теперь мы можем использовать макет везде, где нам нужна ссылка на Fleet:

Преимущество этого подхода в том, что теперь у нас есть центральный Fleet mock для всех тестов. Если подпись меняется, мы просто меняем макет в одном месте, независимо от того, сколько тестов его используют.

На этом этапе наш код должен успешно скомпилироваться с npm start, и все тесты должны пройти с npm t:

Первый Корабль

Большой! Но Fleet без корабля не имеет смысла! Пришло время создать!

Каждый Ship должен принадлежать какому-то Fleet:

Превосходно! Теперь Fleet может инициализировать Ships и управлять ими. Как? Так же, как и любой другой Entity! С помощью своих детей:

Так же, как Game обрабатывает Fleet и Grid, Fleet обрабатывает Ships. Сначала я определяю частный массив для отслеживания всех кораблей. Затем я строю и пробуждаю три Ships. Наконец, я удостоверяюсь, что каждый Ship обновляется, когда Fleet это происходит.

Но почему мы создали ровно три корабля? Это законный вопрос, и, вероятно, не мы отвечаем на него. Это должен быть настраиваемый параметр, который могут изменять дизайнеры игр. Перенесем его в нужное место: Settings!

Отлично! Размер флота теперь является частью глобальной конфигурации! Я подготовил специальный раздел ships в Settings, нам наверняка понадобится много настроек для наших кораблей позже!

Давайте воспользуемся этим новым параметром размера парка в коде:

И, конечно же, мы должны добавить несколько тестов в fleet.spec.ts, чтобы отразить последние изменения:

Здесь мы проверяем, что все корабли были пробуждены и обновлены должным образом. На этом этапе наш код должен успешно скомпилироваться с npm start, и все тесты должны пройти с npm t:

Вы можете найти полный исходный код этого поста в ships-2 ветке репозитория.

Заключение

Отлично сделано! В этом уроке мы обсудили понятие Team и даже создали две команды в нашей игре. Мы также создали наш собственный Fleet,, то есть коллекцию Ships. Мы, наконец, закончили с подготовкой! Следующая часть этой главы будет посвящена рисованию Ship на экране.

Мне бы очень хотелось услышать ваши мысли! Если у вас есть комментарии, предложения, вопросы или любой другой отзыв, не стесняйтесь присылать мне в личном сообщении или оставьте комментарий ниже! Если вам понравилась эта статья, поделитесь ею с другими. Спасибо, что прочитали, до встречи в следующий раз!

Это глава IV из серии руководств «Создание игры с помощью TypeScript». Другие главы доступны здесь:

Получите доступ к экспертному обзору - Подпишитесь на DDI Intel