Во-первых, я не имею в виду управление сценой; Я определяю игровое состояние свободно как любой вид состояния в игре, который имеет значение относительно того, должен ли пользовательский ввод быть включен или нет, или некоторые игроки должны быть временно отключены, и т. Д.
В качестве конкретного примера, скажем, это игра классической Battlechess. После того, как я сделал ход, чтобы взять фигуру другого игрока, начинается короткая битва. Во время этой последовательности игроку не разрешается перемещать фигуры. Итак, как бы вы отслеживали такого рода переходы состояний? Конечный автомат? Простая логическая проверка? Кажется, что последний будет хорошо работать только для игры с очень небольшим количеством изменений состояния такого рода.
Я могу придумать много простых способов справиться с этим, используя конечные автоматы, но я также вижу, как они быстро выходят из-под контроля. Мне просто любопытно, есть ли более элегантный способ отслеживать игровые состояния / переходы.
Ответы:
Однажды я наткнулся на статью, которая довольно элегантно решает вашу проблему. Это базовая реализация FSM, которая вызывается в вашем основном цикле. Я изложил основное краткое изложение статьи в оставшейся части этого ответа.
Ваше основное игровое состояние выглядит так:
Каждое игровое состояние представлено реализацией этого интерфейса. Для вашего примера Battlechess это может означать следующие состояния:
Состояния управляются в вашем государственном движке:
Обратите внимание, что каждому состоянию в какой-то момент требуется указатель на CGameEngine, поэтому само состояние может решить, следует ли вводить новое состояние. В статье предлагается передать CGameEngine в качестве параметра для HandleEvents, Update и Draw.
В конце ваш основной цикл имеет дело только с движком состояния:
источник
Я начинаю с обработки такого рода вещей самым простым способом.
Затем я добавлю проверки против этого логического флага в соответствующих местах.
Если позже я обнаружу, что мне нужно больше особых случаев, чем этот - и только он, - я снова превращаюсь во что-то лучшее. Я обычно использую 3 подхода:
enum { PRE_MOVE, MOVE, POST_MOVE }
и добавьте переходы, где это необходимо. Затем я могу проверить это перечисление, где я использовал проверку на логический флаг. Это простое изменение, но оно уменьшает количество вещей, с которыми вам приходится проверяться, позволяет вам использовать операторы switch для эффективного управления поведением и т. Д.pieceSelectionManager->disable()
или подобное в начале последовательности, иpieceSelectionManager->enable()
. У вас все еще есть флаги, но теперь они хранятся ближе к объекту, которым они управляют, и вам не нужно поддерживать какое-либо дополнительное состояние в коде игры.Вообще говоря, мне никогда не нужно идти дальше этого, когда дело доходит до особых случаев, поэтому я не думаю, что существует риск того, что он «быстро выйдет из-под контроля».
источник
http://www.ai-junkie.com/architecture/state_driven/tut_state1.html - прекрасное руководство по управлению состоянием игры! Вы можете использовать его как для игровых объектов, так и для системы меню, как указано выше.
Он начинает учить о Государственном шаблоне проектирования , а затем приступает к реализации
State Machine
и последовательно расширяет его. Это очень хорошее чтение! Даст вам четкое понимание того, как работает вся концепция и как применять ее к новым типам проблем!источник
Я стараюсь не использовать конечный автомат и логические значения для этой цели, потому что оба они не масштабируемы. Оба превращаются в беспорядок, когда число государств растет.
Я обычно проектирую игровой процесс как последовательность действий и последствий, любое игровое состояние возникает естественным образом без необходимости определять его отдельно.
Например, в вашем случае с отключением ввода игрока: у вас есть какой-то пользовательский обработчик ввода и какая-то визуальная индикация того, что ввод отключен, вы должны сделать их одним объектом или компонентом, поэтому для отключения ввода вы просто отключаете весь объект, не нужно синхронизировать их в каком-либо автомате или реагировать на какой-либо логический индикатор.
источник