Программирование игр Scala - между ООП и ФП - PullRequest
3 голосов
/ 03 января 2012

Я пытаюсь написать обучающую игру в Scala & Processing, намереваясь использовать как можно больше FP. Однако я прихожу к выводу, что игровые объекты с неизменным состоянием в таком приложении невыгодны. Если объект большой, это может привести к довольно интенсивному потреблению памяти в случае постоянного обновления множества таких объектов (следовательно, копирование самого себя в каждом цикле), например, с использованием функции copy(). Каков подход по умолчанию, чтобы решить это? Единственное, что я придумаю - это нарезать объект на крошечные кусочки-объекты, чтобы обновлялись только те, кто нуждается в обновлении, оставляя «большие» объекты одинаковыми.

Ответы [ 3 ]

8 голосов
/ 03 января 2012

Движок игры - это (дискретное) моделирование событий.Как правило, они реализуются с помощью изменяемых структур данных, таких как куча для событий, четырехъядерные деревья для пространственных запросов об объектах и ​​множество хеш-таблиц.

Для каждой из этих структур данных изменяемые варианты работают быстрее.Кроме того, неизменяемые структуры данных производят мусор, который необходимо собирать, поэтому нагрузка на ГХ выше, а ваше приложение работает медленнее.Там, где проблема в реальном времени, паузы ГХ могут быть вредными (например, это может повлиять на частоту кадров в вашей игре), и это особенно верно для платформ с меньшей вычислительной мощностью, таких как Android.

Что касаетсяметод copy() - он не должен копировать весь объект для создания обновленной версии.Если ваш объект организован иерархически в виде дерева (например, в виде иерархии классов дел), то для изменения одного свойства объекта требуется переписать только один путь в этом дереве - вам не нужно будет переписывать все.Тем не менее, это будет дороже, чем просто иметь изменяемую версию и обновление на месте.

Пример:

case class World(map: Array[Item], players: Vector[Player])

case class Player(health: Int, speed: Int, weapon: Weapon, shield: Shield)

case class Weapon(strength: Int, ammo: Int)

Чтобы добавить больше боеприпасов к оружию, вам не нужнополная копия World:

def setAmmo(playerNum: Int, newAmmo: Int, world: World): World = {
  val p = players(playerNum)
  world.copy(players = players.updated(playerNum, p.copy(weapon = p.weapon.copy(ammo = newAmmo))))
}

В этом примере map, другие players и shield измененного Player остаются теми же в памяти и не копируются с нетерпением.

Я бы посоветовал использовать изменяемую структуру данных для представления состояния - если только у вас нет параллельного игрового движка с (например) одним писателем, который имитирует игровое состояние, и целым рядом читателей, которые отображают вывод.обработка звука, сети и т. д. Преимущества неизменяемых структур данных в этом случае практически отсутствуют.

7 голосов
/ 03 января 2012

Прежде всего, не делайте преждевременных оптимизаций. Вы измерили свой код? Может быть, есть какие-то конкретные узкие места?

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

постоянная структура данных - это структура данных, которая всегда сохраняет предыдущая версия сама по себе, когда она изменена; такие данные структуры эффективно неизменны, так как их операции не (заметно) обновить структуру на месте, но вместо этого всегда приводить к новая обновленная структура

Вот замечательный разговор о некоторых из них Даниэль Спивак . Если вы хотите больше, взгляните на Чисто функциональные структуры данных Криса Окасаки.

1 голос
/ 04 января 2012

Просто учтите тот факт, что игровое состояние по своей сути изменчиво.Используйте неизменяемые классы только для таких вещей, которые являются концептуальными значениями, такими как положение, скорость и т. Д. Это может по-прежнему приводить к большому количеству мусора, но работа с включенным анализом escape может помочь.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...