Практикум: 8‑я часть гайда по ООП
Заключительная часть серии статей про ООП, в которой мы создадим небольшой проект.
vlada_maestro / shutterstock
Поздравляю всех, кто осилил все предыдущие статьи и добрался до практикума по ООП на C#. Нам предстоит создать небольшую консольную игру. Мы будем использовать уже изученные возможности ООП, но будет и несколько новых приёмов.
Все статьи про ООП
Какой будет игра
Это будет консольная игра с символьной графикой, в которой можно перемещаться по локации, атаковать NPC, открывать инвентарь и пользоваться предметами.
Устроена игра будет так:
- При запуске вызывается метод InitGame (), в котором будут созданы игровые объекты, предметы и прочее.
- После будет вызван метод Update (), который обновляет состояние игры.
Внутри метода Update () должен находиться цикл со следующими действиями:
- Отрисовка локации или инвентаря.
- Получение нажатой игроком клавиши.
- Передача клавиши в контроллер.
- Контроллер, в зависимости от нажатой клавиши, будет вызывать методы игровых объектов: например, Move () или Use ().
Для управления игрой мы используем три статических класса-контроллера:
- LocationController — перехватывает действия игрока на локации.
- InventoryController — перехватывает действия игрока в инвентаре.
- GraphicsController — управляет выводом.
Игровые данные (размеры локации, список объектов) находятся в статическом классе Game. Объекты будут реализованы с помощью классов GameObject (базовый), Player и NPC. За расположение и перемещение по локации пусть отвечает класс Position.
Предметы реализуются с помощью классов Item (базовый), Potion и Meal. Если предмет может быть использован, то в нём реализуется интерфейс IUsable.
Проект небольшой, но если впихнуть его весь в статью, то для текста места не останется. Поэтому здесь будут только важные части. Чтобы ознакомиться с проектом полностью, скачайте весь исходный код из репозитория на GitHub.
Создание игровых объектов
Начнём с класса GameObjects — он будет родительским для Player и NPC:
Обратите внимание на метод Die () — он выполняется, когда у объекта кончается здоровье. Метод удаляет объект из коллекции Game.Objects, что освобождает память. Схожую функцию выполняют деструкторы — они вызываются перед тем, как объект будет удалён из памяти.
Класс NPC позволит в дальнейшем реализовать логику для игрового ИИ. Player же содержит методы для управления персонажем игрока. Например, чуть позже мы реализуем в нём использование предметов из инвентаря.
Как уже говорилось выше, созданные объекты будут храниться в коллекции статического класса Game. Вот как это выглядит:
Вы могли заметить тут тип данных GameMode — это класс перечислений, который упрощает создание списков в коде:
Одна из альтернатив классам-перечислениям — числа. То есть мы могли бы просто написать так:
Но это не очень удобно, потому что вам придётся всё время смотреть, какое число и для чего вы указывали.
Графика
Теперь, чтобы заставить объекты и локацию отображаться, напишем класс GraphicsController:
Объекты рисуются с помощью символов, которые меняются в зависимости от того, в какую сторону направлен объект.
Теперь можно обновить класс Program, чтобы создать первые объекты и отобразить их в консоли:
Вот что должно быть выведено:
Управление
Чтобы заставить объект игрока двигаться, реализуем управление:
Этот класс проверяет нажатую игроком клавишу и передаёт команды дальше. Например, классу Position, который отвечает за перемещение объектов по локации.
Можно проверить, как работает перемещение:
А вместе с перемещением и боевую систему:
Инвентарь
Инвентарь начинается с класса Item:
Классы Potion и Meal практически идентичные, за исключением выводимых надписей. Поэтому здесь будет показан код только одного из классов:
Можно заметить, что класс наследует интерфейс IUsable:
Теперь, чтобы пользователь мог посмотреть предметы в инвентаре, нужно добавить в GraphicsController следующий метод:
Также в классе Program добавьте в switch с режимами следующий вариант:
Управление будет производиться с помощью InventoryController:
Теперь самое интересное — объект Player:
Тут вы можете увидеть два новых ключевых слова:
- is — проверяет, реализован ли в данном объекте указанный интерфейс;
- as — получает реализацию интерфейса.
Вот что получилось в итоге:
Домашнее задание
На примере небольшой игры мы посмотрели, как используются особенности объектно-ориентированного программирования, чтобы было проще писать код.
Сама игра очень маленькая, и закончить её вам предстоит самостоятельно. Ваша задача — заставить NPC двигаться по какому-нибудь паттерну. Если ИИ натыкается на игрока, то он должен атаковать, прекращая движение по паттерну и начиная преследование, пока игрок не убежит на несколько шагов.
Заключение
Надеюсь, эта серия статей была вам полезной и вы смогли разобраться, что же такое ООП, зачем и как его использовать. На этом серия заканчивается, но если вам хочется узнать больше, то можете записаться на наш бесплатный курс по C#. Там вы напишете столько классов, что ООП станет вашей второй кожей и вы сможете мастерски его использовать.
Больше интересного про код в нашем телеграм-канале. Подписывайтесь!