Программирование игр, создание игрового движка, OpenGL, DirectX, физика, форум
GameDev.ru / Программирование / Форум / Расчёт времени и событий в играх вроде Травиана и Огейм.

Расчёт времени и событий в играх вроде Травиана и Огейм.

Поделиться

Страницы: 1 2 Следующая

НаблюдательПостоялецwww30 окт. 201715:37#0
Суть в чём. В этих играх в реальном игровом времени рассчитываются события перемещения армий, сражений, строительства армий, строительства производственных построек, науки, которые друг на друга влияют.
То есть что-то изобрелось, изменилась скорость производства. Что-то построилось, изменилась скорость строительства армий и так далее. Причём всё это происходит на сервере и независимо от присутствия игрока.
Игрок может зайти только через сутки, и получить все отчёты о событиях по времени.


Понятно, что все расчёты происходят на стороне сервера.
Хотелось бы узнать как такие вещи реализуется программно, в подобных играх.
Обсудить варианты.
Есть специалисты?
Спасибо.

TiendilУчастникwww30 окт. 201716:50#1
Примерно так:

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

Просто и дёшево.

patsanchik3Постоялецwww30 окт. 201716:51#2
Наблюдатель
> в реальном игровом времени рассчитываются события перемещения армий
а в чем сложность то ?
в бд есть профиль игрока (созданный при регистрации игрока)
в профиле есть поля для времени события для армии
сервер по команде клиента и при соблюдении условий (например наличия игровых ресурсов) меняет данные в модели игрока

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

НаблюдательПостоялецwww30 окт. 201717:09#3
Tiendil
То есть ты предлагаешь решать задачу просто скриптовым способом.
А сами предполагаемые события хранить в бд?

А потоки использовать не вариант, дорого?

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

То есть конечно, такой алгоритм изобрести можно. Но хороший ли это вариант?
Ну, а вообще очередь событий, с пересчётом - вариант неплохой.

Через паттерн Наблюдатель нормально будет? В джанго через сигналы.


patsanchik3
> а в чем сложность то ?
Немного не в том, что ты описывал.
Проблема немного в другом.

Правка: 30 окт. 2017 17:13

TiendilУчастникwww30 окт. 201717:34#4
Наблюдатель
>То есть ты предлагаешь решать задачу просто скриптовым способом.
Забудь понятия "скрипт", "скриптовые способы" и т.д. Это лингвистические паразиты, которые только путают и пришли из седых 90-ых, когда писали на perl прямо в html шаблонах.
Кроме того, эти понятия отражают способ реализации, а не суть реализуемой сущности. Лучше использовать, в зависимости от случая: утилита, рабочий (worker), сервис.

>А сами предполагаемые события хранить в бд?
Где удобно. Смотреть надо по стеку технологий. Можно в реляционной БД, можно в не совсем реляционной, можно не в БД. Можно микросервис написать, который будет всё это в памяти держать и разруливать. Подход я описал, а реализация будет сильно зависить от окружения, команды, навыков и продукта.

> А потоки использовать не вариант, дорого?
Для чего конкретно? Если по потоку на игрока, то очень дорого.

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

>Через паттерн Наблюдатель нормально будет?
Если не вдаваться в подробности реализации, то да.

> В джанго через сигналы.
Зависит от того, что конкретно ты через них собрался релаизовывать. Сигналы в Django локальны для процесса. Если будет два одновременных запроса, то будет дублирование операций.

В общем случае могу дать ещё пару рекоменаций:

- реализовывать через утилиту, которая запускается по крону, загружает всё из базы, пересчитывае и выгружает проще, но будут большие проблемы с производительностью при росте количества сущностей в игре.
- реализовывать через отдельный сервис с каким-нибудь rest api, который всё держит в памяти, сложнее, но будет работать быстрее.

НаблюдательПостоялецwww30 окт. 201717:43#5
Tiendil
> Нужно пересчитывать не в момент прихода игрока, а в момент совершения события, влияющего на персчёт.
Вот это не получится. У меня программа на запрос-ответ работает. То есть пока к ней кто-то не обратится, то она ничего не делает.

А как во всяких травианах такую кухню устраивают, не вкурсе?


> - реализовывать через отдельный сервис с каким-нибудь rest api, который всё держит в памяти, сложнее, но будет работать быстрее.
Вот я уж не знаю, что тут будет сложнее и дешевле в обслуживании. Такую вещь как альтернативный вариант как раз и рассматриваю.
Имеешь ввиду реализовать взаимодействие по принципу REST между приложениями?
То есть повесить на тот же адрес, но другой порт, и дать им возможность общаться через http?

Правка: 30 окт. 2017 17:46

TiendilУчастникwww30 окт. 201717:54#6
Наблюдатель
> Вот это не получится. У меня программа на запрос-ответ работает. То есть пока к ней кто-то не обратится, то она ничего не делает.
В вебе сейчас только бложики работают в таком режиме. Всегда есть как-минимум задачи, выполняемые по расписанию (например, снятие бекапа). Фоновые процессы - это нормально.

Но даже в этом случае можно по cron-у запускать простую утилиту, которая дёргает нужный http адрес. Но не нужно так делать.

TiendilУчастникwww30 окт. 201717:55#7
Наблюдатель
> То есть повесить на тот же адрес, но другой порт, и дать им возможность общаться через http?
Можно и на другой адресс. Гугли про микросервисы. Можно и не по http, тут надо смотреть что оно делать будет.
НаблюдательПостоялецwww30 окт. 201718:06#8
Tiendil
> Можно и на другой адресс. Гугли про микросервисы. Можно и не по http, тут надо смотреть что оно делать будет.
Я думаю в данном варианте это просто процесс, или поток который как раз и держит в памяти все события.
Но опять же. Он будет считать время на каждое событие. А это значит по потоку на каждый отсчёт. Верно?

Можно реализовать как rest. Но тут ещё вопрос.
Выносить в отдельный сервис менее удобно, так как его тогда надо отдельно запускать.
Предположим джанга запущена на двух процессах, тогда каждый запустит по потоку.
А мне надо чтобы поток был один.
Я могу как-то защитить их дублирования?

TiendilУчастникwww30 окт. 201718:15#9
Наблюдатель
> Но опять же. Он будет считать время на каждое событие. А это значит по потоку на каждый отсчёт. Верно?
Нет. Зачем? Используй очередь с приоритетом: https://ru.wikipedia.org/wiki/%D0%9E%D1%87%D0%B5%D1%80%D0%B5%D0%B… %D0%BE%D0%BC_(%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5)

В питоне она в стандратной библиотеке есть: heapq

> Предположим джанга запущена на двух процессах, тогда каждый запустит по потоку.
Не джангой единой живы мы. Можешь погуглить про asyncio и прочую асинхронщину.

Но и в Django можно один поток запустить и будет счастье, если событий не много будет. Если не кртичен ответ от сервиса, то можно и не http, а какую-нибудь очередь использовать (например rabbitmq) в которую просто слать события и забывать, а отдельный поток django будет их выбирать по мере своей готовности.

>Я могу как-то защитить их дублирования?
Тут всё очень зависит от всего проекта в комплексе. В некоторых случаях можно, в некоторых нельзя.

НаблюдательПостоялецwww30 окт. 201718:21#10
Tiendil
Спасибо, большое, за информацию.
Надо теперь обдумать эти варианты.
НаблюдательПостоялецwww30 окт. 201718:21#11
Tiendil
> Можешь погуглить про asyncio и прочую асинхронщину.
Ну это тоже как потоки, почти. Только памяти меньше кушают, как я понял.
TiendilУчастникwww30 окт. 201718:25#12
Наблюдатель
> Ну это тоже как потоки, почти.
Не почти. Есть разница между параллельностью и конкурентностью. Погугли :-)
НаблюдательПостоялецwww30 окт. 201718:47#13
Tiendil
> Есть разница между параллельностью и конкурентностью.
А разве GIL не сводит на нет параллельность?

asyncio в одном потоке итерирует вычисления.

Правка: 30 окт. 2017 18:49

TiendilУчастникwww30 окт. 201719:19#14
Наблюдатель
> А разве GIL не сводит на нет параллельность?
Не всегда, особенно не в случае веба.

В вебе много io операций (чтение/запись в сеть, чтение/запись в базу/кеш), они не блокируются.

Поэтому в случае Django получается, что процесс большую часть времени простаивает (ждёт пока данные отправятся или получатся), а в случае asyncio, пока одна сущность (coroutine) ждёт, другая может работать. Таким образом, один процесс может конкурентно (но не параллельно) выполнять несколько запросов (например, http), не влияя на длительность их выполнения. Это позволяет, например. сильно экономить RAM и вообще работать в одном пространстве памяти.

Правка: 30 окт. 2017 19:20

Страницы: 1 2 Следующая

/ Форум / Программирование игр / Игровая логика и ИИ

2001—2017 © GameDev.ru — Разработка игр