Примеры работы с ООП: 8-я часть гайда по объектно-ориентированному программированию / Skillbox Media
Заключительная часть серии статей про ООП, в которой мы создадим небольшой проект.
Бесплатный курс по Python ➞ Мини-курс для новичков и для опытных кодеров. 4 крутых проекта в портфолио, живое общение со спикером. Кликните и узнайте, чему можно научиться на курсе.
Узнать большеПоздравляю всех, кто осилил все предыдущие статьи и добрался до практикума по ООП на 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 — получает реализацию интерфейса.
Вот что получилось в итоге: