Готовый перевод Game Programming Patterns / Паттерны программирования в играх: 3.3 Type Object

Цель

Мотивация

Представьте себе, что мы работаем над ролевой фэнтези игрой.

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

У монстров есть много разных характеристик: здоровье, атака, графика, звуки и т.д,

но для примера нам будут нужны только первых две.

У каждого монстра есть значение текущего здоровья.

Вначале оно полное, но каждый раз когда при получении урона уменьшается.

Также монстры обадают строкой атаки.

При каждой атаке монстрами нашего героя, она каким-то образом будет показывается пользователю.

( Пока нам все равно как)

Дизайнеры сказали нам, что существуют различные породы монстров,такие как дракон или тролль.

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

Порода устанавливает стартовое количество здоровья.У дракона его больше чем у тролля, что делает его более живучим.

Также она определяет строку атаки: все монстры с одинаковой породой атакуют одним и тем же способом.

Типичная ООП ответ

Учитывая игровой дизайн, откроем текстовый редактор и начнем программировать.

В соответствии с проектом, дракон это один тип монстра, тролль другой, и так далее с другими породами.

Мысля объектно-ориентировано, приходим к выводу, что нам нужен класс Monster:

Это так называемое “is-a” отношение.

Согласно ООП, так как дракон является монстром, то модель Dragon должна быть подклассом класса Monster.

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

class Monster

{

public:

virtual ~Monster() {}

virtual const char* getAttack() = 0;

protected:

Monster(int startingHealth)

: health_(startingHealth)

{}

private:

int health_; // Current health.

};

Публичный метод getAttack() определяет строку, которая будет отображаться при атаке монстром нашего героя.

Каждый унаследованный класс будет переопределять этот метод, чтобы обеспечить разные уведомления при атаке.

Конструктор объявлен как protected и принимает в качестве аргумента начальное здоровья монстра.

Мы объявим классы для каждой породы, которые будут обеспечивать свои собственные открытые конструкторы, в которые будет передаваться стартовое количество здоровья для каждой отдельной породы монстров..

Теперь взглянем на пару подобных подклассов.

class Dragon : public Monster

{

public:

Dragon() : Monster(230) {}

const char* getAttack() {

return "The dragon breathes fire!"

;

}

};

class Troll : public Monster

{

public:

Troll() : Monster(48) {}

virtual const char* getAttack() {

return "The troll clubs you!"

;

}

};

Восклицательный знак делает смысл более захватывающим!

Каждый класс унаследованный от Monster, передает начальное количество здоровья, и переопределяет метод getAttack().

Все работает как и ожидалось и вскоре у нас есть наш герой, бегающий по округе и убивающий разного рода тварей.

Перекомпилировать игру.

Повторить.

2 класса.

Шаблон

Когда это использовать

Ничего не напоминает?

Переведено на Нотабеноиде
http://notabenoid.org/book/51192/215224

Переводчики: asbestovek, kabanov

Настройки

Готово:

13.75% КП = 1.0

Непереведённые фрагменты будут пропущены.