Существует ли общая методика обработки состояния (в целом) в функциональном языке программирования? В каждом (функциональном) языке программирования есть решения для обработки глобального состояния, но я хочу избежать этого, насколько смог.
Все состояние чисто функциональным образом является функциональными параметрами. Поэтому мне нужно поместить все игровое состояние (гигантскую хэш-карту с миром, игроками, позициями, счетом, активами, врагами и т. Д.) В качестве параметра для всех функций, которые хотят манипулировать миром при заданном входе или триггере. , Сама функция выбирает соответствующую информацию из BLOB-объекта игрового состояния, что-то с ним делает, манипулирует игровым состоянием и возвращает игровое состояние. Но это похоже на решение проблемы бедняков. Если я помещу целое состояние игры во все функции, для меня не будет никакой пользы в отличие от глобальных переменных или императивного подхода.
Я мог бы поместить только соответствующую информацию в функции и вернуть действия, которые будут предприняты для данного ввода. И одна функция применяет все действия к игровому состоянию. Но большинству функций нужно много «актуальной» информации. move()
нужна позиция объекта, скорость, карта для столкновения, положение всех врагов, текущее здоровье, ... Так что этот подход тоже не работает.
Итак, мой вопрос: как мне справиться с огромным количеством состояний в функциональном языке программирования - особенно для разработки игр?
РЕДАКТИРОВАТЬ: Есть некоторые игровые рамки для создания игр в Clojure. Подход к решению этой проблемы частично состоит в том, чтобы нарезать все объекты в игре как «сущности» и поместить их в огромную сумку. Гигант Основная функция держит экран и сущности и обработки событий ( :on-key-down
, :on-init
, ...) для этого лиц и запустить главный цикл отображения. Но это не чистое решение, которое я ищу.
move()
вы, вероятно, должны передавать «текущий» объект (или идентификатор для него), а также мир, в котором он движется, и просто получать текущее положение и скорость ... тогда выход - это весь физический мир, или, по крайней мере, список измененных объектов.Ответы:
Побочные эффекты и состояние в функциональных языках программирования - более широкая проблема в информатике. Если вы не сталкивались с ними раньше, возможно, взгляните на монады . Тем не менее, будьте осторожны: они являются довольно продвинутой концепцией, и большинство моих знакомых (включая меня) изо всех сил пытаются понять их. Есть много, много учебников онлайн, с различными подходами и требованиями к знаниям. Лично мне больше всего понравился Эрик Липперт.
Эрик Липперт на Монадах
Некоторые вещи, чтобы рассмотреть, хотя:
Несколько заключительных мыслей:
В общем, я думаю, что даже если это может быть интересно с научной точки зрения, я сомневаюсь, что этот подход практичен и стоит усилий.
источник
Я написал несколько игр, используя F # (мультипарадигма, нечистый, функционально-первый язык), с подходами, варьирующимися от ООП до FRP . Это широкий вопрос, но я сделаю все возможное.
Мой предпочтительный способ - иметь неизменный тип, представляющий всю игру
State
. Затем у меня есть изменяемая ссылка на текущий,State
который обновляется каждый тик. Это не совсем чисто, но оно ограничивает изменчивость в одном месте.Не правда. Поскольку
State
тип является неизменяемым, вы не можете иметь какой-либо старый компонент, изменяющий мир плохо определенными способами. Это решает самую большую проблему сGameObject
подходом (популяризируемым Unity): трудно контролировать порядокUpdate
вызовов.И в отличие от использования глобалов, он легко тестируется на единицах и распараллеливается,
Вы также должны написать вспомогательные функции, которые получают под-свойства состояния, чтобы устранить проблему.
Например:
Здесь
update
действует на все государство, ноupdateSpaceShip
действует только на человекаSpaceShip
в изоляции.Я бы предложил создать
Input
тип, содержащий состояния клавиатуры, мыши, геймпада и т. Д. Затем вы можете написать функцию, которая принимаетState
иInput
возвращает следующееState
:Чтобы дать вам представление о том, как это сочетается, общая игра может выглядеть примерно так:
Для простых игр вы можете использовать подход выше (вспомогательные функции). Для чего-то более сложного, вы можете попробовать « линзы ».
Вопреки некоторым комментариям здесь, я настоятельно рекомендую писать игры на (нечистом) функциональном языке программирования или, по крайней мере, попробовать! Я обнаружил, что это делает итерацию быстрее, кодовые базы меньше и ошибки реже.
Я также не думаю, что вам нужно изучать монады, чтобы писать игры на (нечистом) языке FP. Это потому, что ваш код, скорее всего, будет блокирующим и однопоточным.
Это особенно верно, если вы пишете многопользовательскую игру. Тогда с этим подходом все станет намного проще, поскольку он позволяет тривиально сериализовать состояние игры и отправлять его по сети.
Что касается того, почему больше игр не написано таким образом ... Я не могу сказать. Однако это верно для всех областей программирования (за исключением, возможно, финансов), поэтому я бы не стал использовать это в качестве аргумента, что функциональные языки плохо подходят для игрового программирования.
Также стоит прочитать « Чисто функциональные игры» .
источник
То, что вы ищете, это разработка игр FRP.
Некоторые видео введения:
«Управление временем и пространством: понимание многих формулировок FRP» Эвана Чаплицки
Бодил Стокке: Реактивная разработка игр для проницательного хипстера [JSConf2014]
Мне нравится этот разговор с Кармаком, он рассказывает о своем опыте чисто функционального программирования в разработке игр. Основной доклад Джона Кармака на Quakecon 2013, часть 4.
На 100% возможно и предпочтительнее сделать основную игровую логику чисто функциональной, отрасль в целом просто отстает, застряв в одной парадигме мышления.
Это возможно сделать и в Unity.
Чтобы ответить на вопрос, новое состояние игры будет обновляться / создаваться каждый раз, когда что-то движется, как говорит Кармак в своем выступлении, это не проблема. Резкое сокращение накладных расходов на когнитивные функции, обусловленное исключительно функциональной, легко обслуживаемой и гибкой архитектурой, значительно влияет на производительность, если она вообще существует.
источник