Спрайты как актеры

12

Я не опытный в вопросах разработки игр, но как программист. На языке Scala у вас может быть масштабируемая многозадачность с актерами, очень стабильная, как я слышал. Вы можете даже запустить сотни тысяч одновременно без проблем.

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

Будет ли это иметь смысл для игры? Имея это многозадачность, как это? В конце концов, он будет работать на JVM, хотя в настоящее время это не должно быть большой проблемой.

РЕДАКТИРОВАТЬ:

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

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

Другое преимущество, которое я вижу, заключается в том, что в Scala вы можете иметь RemoteActorsтакой же способ, но работать на другом компьютере. Так что, возможно, это также может упростить сетевые игры.

Я собираюсь встроить это в мой движок Scala 2D, как только смогу.

Lanbo
источник
Мне было бы очень интересно узнать, как это получается. Я смотрел на Scala пару раз, но никогда не углублялся в это раньше.
Davy8
Многие утверждают, что для явной поддержки многоядерных процессоров вам лучше использовать потоки, а не процессы (и акторы Scala моделируют процессы). Это потому, что вы можете воспользоваться общей памятью между потоками. Конечно, это подвержено ошибкам, в отличие от модели Actor.
Килотан
Акторы Scala мультиплексируются поверх пула потоков, так что они могут быть более легкими, чем потоки. Это означает, что они могут манипулировать совместно используемой памятью для связи при условии, что она синхронизирована должным образом. Если вы используете удаленных актеров, то они могут находиться в разных процессах, и единственный способ связи - это отправка сообщений.
axel22

Ответы:

7

Я не пробовал, но я программист Scala, и я бы сказал, что это не лучший подход. Спрайты должны быть анимированы синхронно. Актеры не имеют никаких гарантий, что они будут выполнены честно - поэтому некоторые спрайты могут быть быстрее других, а это не то, что вам нужно. Возможно, вы захотите использовать барьер для их синхронизации, но тогда - зачем использовать актеров. Если вы полагаетесь только на передачу сообщений, реализация такого рода синхронизации (создание барьера для 1000+ участников) является излишним.

Еще одна проблема - что бы вы использовали для передачи сообщений? Вам нужны ваши спрайты для общения? Вы можете послать сообщение от главного действующего лица, сообщив каждому спрайту, что нужно перейти к следующему кадру, но с точки зрения производительности это на величины и величины больше, чем прямой вызов методов и итерация набора спрайтов.

Сдается мне, что здесь вам нужна какая-то очень легкая многозадачность, и вообще никаких сообщений. Если вы хотите убедиться в этом, то, вероятно, лучше всего использовать собственную реализацию, подобную актерской реализации, которая обеспечивает справедливость, но это слишком большая работа для слишком малого выигрыша. Другая вещь, на которую стоит обратить внимание, - это функциональное реактивное программирование, и scala.reactя считаю, что оно лучше подходит для этого варианта использования.

Я реализовал 2d изометрический игровой движок в Scala. Я использовал только одного глобального актера для обновления видимых спрайтов, которые были анимированы.

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

Тем не менее, на вашем месте, я бы попробовал это, просто чтобы посмотреть, что происходит.

axel22
источник
1

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

Что это будет за событие?

Будет ли это событие, которое вы излучаете один раз за кадр?

И если да, то как это изменило систему на практике?

Первоначально изучая объектную ориентацию в контексте C ++, я узнал, что некоторым людям нравится думать о таком утверждении, xyz.doThis(x)как значение «отправить сообщение doThis в xyz (с полезной нагрузкой x) и ждать немедленного ответа». При рассмотрении на этом уровне нет никакой внутренней разницы между системой, основанной на событиях или сообщениях, и обычной процедурной.

Kylotan
источник
Актеры являются многопоточным решением. Сообщения не являются синхронными. Актеры Scala (концепция от Erlang) позволяют легко программировать многоядерные системы.
Эллис
У вас есть смысл, но разница здесь в том, что спрайт на основе актера не блокирует игровой цикл во время выполнения действия, тогда как метод-подход ждет, пока не xyz.doThis(x)будет сделано. Я думаю, что это может даже помочь ускорить игровую логику, особенно в многоядерных системах.
Ланбо
Это облегчает распределение обработки сущностей по нескольким ядрам, правда. Но цена этого в том, что вы не можете легко ссылаться от одного актера к другому без дополнительных сообщений или дополнительных данных, отправляемых в сообщениях. Таким образом, вы быстро понимаете, что наивный подход здесь не поможет вам - вы можете сформулировать актовый способ выполнения обновлений?
Килотан
В настоящее время я экспериментирую с каким-то распределенным обновлением: мои актеры похожи на узлы в древовидной структуре, а обновление корня обновляет дочерние элементы путем рассылки сообщений. Также истинным преимуществом будет сетевое взаимодействие: в Scala Actor и RemoteActor (Actor в другой системе) могут адресоваться одинаково, с помощью одних и тех же сообщений.
Ланбо
Да, но проблема не в том, что обновление запускается как таковое, а в том, что получатель сообщения имеет всю информацию, необходимую для его действия.
Kylotan
0

Это крутой подход к обновлению игровых объектов. Я не знаю, Scala, но я говорю, попробуйте и посмотрите, как это получается, и еще лучше опубликовать свои результаты!

Основные вопросы, которые возникают у меня в голове: Как вы управляете тем, как часто одни игровые объекты обновляются по сравнению с другими? Будете ли вы беспокоиться о том, что спрайтеры будут выполнять слишком много циклов, чтобы система рендеринга не успевала рисовать кадр каждые 1/60 | 30–24?

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

michael.bartnett
источник
Самое замечательное в Scala Actors заключается в том, что они управляются сообщениями. У каждого из них есть своя собственная очередь сообщений / событий. Я не уверен, должно ли 'Draw' быть сообщением или методом для вызова. Я думаю, что это будет последним, так что Sprite может быть нарисован в любое время, независимо от состояния их очереди событий. И они могут отправлять друг другу сообщения, чтобы убедиться, что все сделано в определенном порядке.
Ланбо
Будьте осторожны, я не думаю, что каждый спрайт имеет метод Draw или событие Draw, было бы полезно, за исключением, может быть, в качестве флага для переключения видимости. На этапе рендеринга игрового цикла порядок отображения спрайтов на экране оказывает большое влияние на результат. Если у вас есть один спрайт, который расположен перед другим (измерение находится по направлению к монитору), вы хотите, чтобы этот спрайт отображался вторым. Я вижу, что актеры Scala полезны для обновления / логики игрового цикла.
michael.bartnett
Обычно у вас есть только метод draw, поэтому его реализация не должна сильно отличаться от обычного способа работы со спрайтами.
Ланбо
Ах, хорошо, я неправильно понял, что вы описывали. Я каким-то образом представлял себе спрайтов, отображающих себя всякий раз, когда они хотят. Дайте нам знать, как это получается!
michael.bartnett
0

Ну, я не такой уж и программист, но не вижу проблем в вашем предложении. Я даже не думал о таком способе развития актеров.

Это может быть довольно сложной задачей, так как IA должен быть очень точным, чтобы избежать непредвиденного поведения, но, кроме того, я вижу, что это довольно хорошее предложение

Карлос Валенсуэла
источник
0

Если под спрайтом вы имеете в виду игровую сущность, то обязательно.

Игровые сущности никогда не должны рисовать себя. Они должны обновить графический дескриптор, который описывает, где и как они должны быть нарисованы. Система рендеринга или граф сцены или все, что делает фактический рисунок. Существует одна графическая карта, кроме того, она должна синхронизироваться каждые 16 мс. Такая установка просто не работает для распределенной асинхронной обработки.

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

Я не разработчик Scala, но я немного поработал с Erlang. Так что если какая-то из моих терминов Scala неверна, пожалуйста, прости меня.

deft_code
источник