Вопрос по sockets – «Алгоритм движения» в многопользовательских (MMO) играх клиент-сервер?

8

Я писал многопользовательскую игру 2D-флэш и сервер сокетов. Мой оригинальный план для алгоритма движения между клиентом и сервером был следующим:

The client informs the server about the player's movement mode (moving forward or not moving) and the player's turning mode (not turning, turning left or turning right) whenever these change. The server loops all players every few milliseconds and calculates the angle turned and distance moved, based on the difference in time. The same calculation is done by the client.

Мой текущий расчет для клиента (такая же математика используется на сервере) == & gt;

Turning

var newTimeStamp:uint = UtilLib.getTimeStamp(); //set current timeStamp
                var rot:uint = Math.round((newTimeStamp - turningTimeStamp) / 1000 * 90); //speed = x degrees turning every 1 second
                turningTimeStamp = newTimeStamp; //update timeStamp
                if (turningMode == 1) //left
                {
                    movementAngle = fixAngle(movementAngle - rot);
                }
                else if (turningMode == 2) //right
                {
                    movementAngle = fixAngle(movementAngle + rot);
                }

private function fixAngle(angle:int):uint //fixes an angle in degrees (365 -> 5, -5 -> 355, etc.)
        {
            if (angle > 360)
            {
                angle -= (Math.round(angle / 360) * 360);
            }
            else if (angle < 0)
            {
                angle += (Math.round(Math.abs(angle) / 360) + 1) * 360;
            }
            return angle;
        }

Movement

var newTimeStamp:uint = UtilLib.getTimeStamp(); //set current timeStamp
                var distance:uint = Math.round((newTimeStamp - movementTimeStamp) / 1000 * 300); //speed = x pixels forward every 1 second
                movementTimeStamp = newTimeStamp; //update old timeStamp
                var diagonalChange:Array = getDiagonalChange(movementAngle, distance); //with the current angle, howmuch is dX and dY?
                x += diagonalChange[0];
                y += diagonalChange[1];

private function getDiagonalChange(angle:uint, distance:uint):Array
        {
            var rAngle:Number = angle * Math.PI/180;
            return [Math.round(Math.sin(rAngle) * distance), Math.round((Math.cos(rAngle) * distance) * -1)];
        }

Кажется, это отлично работает. Чтобы учесть отставание, сервер время от времени корректирует информацию клиента, отправляя эти данные.

С этой системой очень малая пропускная способность используется для управления движением. Однако различия между координатами и углами моего сервера и клиента слишком велики. Должен ли я, возможно, расширить свой «алгоритм», чтобы также учесть задержку, которую имеет пользователь? Или есть ли более эффективные способы обработки перемещения в многопользовательских играх на клиентских серверах с высокой производительностью?

Ваш Ответ

3   ответа
6

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

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

В основном это просто необходимо, чтобы обнаружить мошенничество.

Остановка, борьба и т. Д. Потребовали бы отправки позиции вместе с атакой, а действия, инициируемые позициями, будут запускаться только после того, как клиент отправит обновление для этой позиции, но будут основаны на сервере.

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

Ответ на комментарий:

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

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

Обнаружение мошенничества можно даже отключить для проверки производительности или установить случайную проверку.

Примечание. Чтобы это работало, клиенту необходимо отправить всю информацию о столкновении / положении на объектах в пределах дальности полета.

Error: User Rate Limit Exceeded Tom
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded Tom
Error: User Rate Limit Exceeded
1

Есть два способа, которыми я могу думать об этом - заставить клиент выдавать команды на сервер & amp; сервер будет лучшим хранителем карты.

Или сохраните карты в клиентах & amp; клиенты должны будут устанавливать соединения с другими клиентами, которых они «близки»; для того, чтобы сделать движение, при этом ведение записей осуществляется сервером & amp; проверено несколькими сверстниками (хакерской полицией).

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

Error: User Rate Limit Exceeded Tom
Error: User Rate Limit Exceeded
0

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

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

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

Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded Tom

Похожие вопросы