Готовый перевод 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
Настройки
Готово:
