php - как заставить работать очередь событий в автономном режиме в браузерных играх
Размышляя о создании браузерных игр, я столкнулся с тревожной проблемой. Во многих играх есть так называемая "очередь событий", которая работает следующим образом. У меня есть "армия", и я посылаю ее своему противнику. Я занимаю некоторое время. Когда моя "армия" получает расположение "армии" противника, происходит бой, рассчитанный на то, чтобы моя "армия" проиграла или выиграла. Все хорошо, когда я или мой оппонент в игре. Какая-то Ajax-работа может управлять вызовом php-скрипта и вычислять бой, а затем сохранять его результат в базе данных. Но как это может работать, если ни я, ни противник не вошли в систему, когда происходит битва? Хорошим примером такой игры является Ogame, когда вы отправляете корабли на другую планету, и он может встретить свое предназначение, когда вы выйдете из системы, проведете бой, получите источники информации о вашем враге и возвращаетесь, поэтому он рассчитывает не только космические корабли на планете, но и количество ресурсов в этот конкретный момент.
Я думал, что смогу сэкономить время атаки как атакующего, так и его противника в строках базы данных и рассчитать бой, когда любой из игроков войдет в игру, но у этого решения есть много недостатков. Например, если есть третий игрок, который будет атаковать, прежде чем я нападу на своего оппонента, он изменит статистику истории армии (потому что он может убить часть своей армии), и у меня будет много последствий. Также, если ни один из игроков не выйдет из игры в течение длительного времени, они появятся в игре, поскольку они не сражаются, и это не будет правдой
Есть ли у вас идеи, как сделать такую очередь событий? Я думаю, что использование cron также не очень хорошая идея - его иногда можно использовать редко, и, если есть тысячи игроков, тысячи экземпляров cron могут быть причиной снижения производительности. Любая концепция будет оценена - надеюсь, я достаточно хорошо описал свою проблему:)
2 ответа
В вашей базе данных создайте таблицу "заданий" (все, что вам нужно, плюс дата EXPIRE - когда задание завершено), и каждый раз, когда пользователь вызывает создание задания (например, перемещает корабли из одного кластера в другой), создайте новая запись в этой таблице с установленным EXPIRE временем прибытия кораблей в целевой кластер.
Затем каждый раз, когда кто-нибудь (!) Загружает какой-либо сайт (даже стартовую страницу), скрипт проверяет наличие заданий в очереди, которые уже должны были быть выполнены. Если есть какие-либо задания, в которых EXPIRE меньше, чем NOW, он выполняет эту работу (или, для больших заданий, запускает процесс php cli для выполнения этой работы).
Если предположить, что это 2012-12-28 12:00, в игре есть два игрока A и B, где A начинает атаку на B, которая занимает 6 часов. Задание создается с EXPIRE=2012-12-28 18:00 и контентом "Fleet foobar attack B".
Случай A: Теперь A выходит из системы и ничего не происходит до 19:00. B входит в систему, и, прежде чем что-либо еще произойдет (это важно для того, чтобы "уведомления" или входящие сообщения не появлялись несинхронно), сценарий видит, что задание находится в таблице и просрочено. Сценарий выполняет задания и создает уведомление для B о том, что он был захвачен огромным флотом из A. Задание выполнено, все в порядке (кроме настроения B).
Случай B: A выходит из системы. В 18:30 анонимный пользователь заходит на стартовую страницу. Сценарий снова просматривает таблицу заданий и выполняет задание. Б входит в 19:00 и видит уведомление о его потере. Работа выполнена.
Идея создания очереди событий без CRON в моем проекте заключается в следующем:
Все события имеют время окончания. Я использую сырые временные метки UNIX time() для простых операций сравнения.
Когда пользователь "щелкает" (открывает любую страницу игры), механизм очереди выбирает все события, которые "закончились" <= текущее время (), в соответствии с приоритетом. События, которые происходят в одну и ту же секунду, выполняются с высокого приоритета на низкий.
Если в игре нет пользователей - никому не нужны события. Просто так просто:) Игра спит до тех пор, пока кто-нибудь не войдет в игру и не откатится в очередь событий, как описано во втором шаге.
Вы можете добавить такую же функциональность на любой веб-сайт, который имеет периодические события и достойный ежедневный трафик сайта.
(На самом деле я также сделал cron.php по требованию)