Достижение разблокировано
Допустим, мы хотим добавить систему достижений
в нашу игру: игроки будут получать значки за выполне-
ние десятков разнообразных заданий, например «Убить
100 демонов-обезьян», «Упасть с моста» или «Завершить
уровень с помощью дохлого хорька» (рис. 4.1).
Глава 4
Как и многие другие
вещи в программирова-
нии, модель MVC была
изобретена разработчи-
ками Smalltalk в семиде-
сятые годы. Хотя разра-
ботчики Lisp
утверждают, будто при-
думали эту архитектуру
еще в шестидесятые,
но не посчитали нуж-
ным ее задокументиро-
вать.
Рис. 4.1
. Непреднаме-
ренно двойной смысл
60
Наблюдатель (Observer) —
Паттерны программирования игр
Это сложно реализовать, так как мы подразумеваем
достаточно широкий диапазон достижений, для разбло-
кировких которых нужно выполнять абсолютно разные
задания. Если мы не будем осторожны, отростки нашей
системы достижений будут забираться в самые темные
углы кода. Конечно, «Упасть с моста» непременно свя-
зано с физическим движком, но действительно ли мы
хотим увидеть вызов
unlockFallO Bridge()
прямо
в сердце линейной алгебры алгоритма разрешения кол-
лизий?
Что мы хотели бы, так это поместить весь код, свя-
занный с одним аспектом игры, в одно расположение.
Но достижения связаны со множеством различных ас-
пектов игрового процесса, вот в чем загвоздка. Как же
можно реализовать нашу задумку, не связывая код си-
стемы достижений с каждым из них?
Для этого и предназначен паттерн Наблюдатель
(Observer). Он позволяет одному фрагменту кода объ-
явить: «произошло что-то интересное»,
не заботясь
о том, кто получает уведомление
.
Например, у нас есть код, отвечающий за физику, он
симулирует гравитацию и отслеживает, какие тела спо-
койно лежат на ровных поверхностях, а какие падают
под неумолимой силой гравитации. Чтобы реализовать
достижение «Разрушить мост», мы могли бы просто по-
местить код достижения прямо в движок, но это было бы
ужасно. Зато мы можем сделать вот что:
void Physics::updateEntity(Entity& entity)
{
bool wasOnSurface = entity.isOnSurface();
entity.accelerate(GRAVITY);
entity.update();
if (wasOnSurface && !entity.isOnSurface())
{
notify(entity, EVENT_START_FALL);
}
}
Это риторический во-
прос. Ни один уважаю-
щий себя создатель фи-
зических движков
никогда не позволил бы
нам испортить свою
прекрасную математику
каким-то случайно туда
попавшим куском игро-
вого процесса.
Do'stlaringiz bilan baham: |