Заполняя контекст из вашего предыдущего вопроса, я понимаю, что вы отправляете весло и мяч позиции от одного клиента к другому. Однако, пока клиенты согласны с тем, где находятся лопасти в каждый момент времени, движение мяча полностью определено (за исключением ошибок округления), и вы должны экспериментировать с нулевым заиканием мяча. Каждый клиент должен сохранять свое внутреннее состояние с положениями и скоростями ракеток и мяча. Псевдокод будет похож на следующий:
// input thread
if input changed,
alter paddle speed and/or direction
send timestamped message to inform my opponent of paddle change
// incoming network thread
if paddle packet received
alter opponent's paddle speed and/or direction at time it was sent
fix any errors in previously extrapolated paddle position <--- Easy
if ball-packet received
fix any errors in ball position and speed <--- Tricky
// update entities thread
for each entity (my paddle, opponent paddle, the ball)
compute updated entity position, adjusted by time-since-last-update
if ball reached my end, send ball-packet to other side
draw updated entity
Это предполагает, что происходит обмен двумя типами пакетов:
- Пакеты манипуляторов содержат временные метки положения и скорости манипуляторов и отправляются всякий раз, когда клиент изменяет скорость своего манипулятора.
- Пакеты с мячом представляют собой позиции с отметкой времени + скорость мяча и отправляются всякий раз, когда мяч достигает клиентской (локальной) стороны, независимо от того, отскакивает он от ракетки или нет.
Псевдокод выполняет экстраполяцию («предположим, что все идет как обычно») для всех неизвестных в потоке update-entities. Единственная точка, где возникают проблемы, отмечена <---
стрелками.
Вы можете легко скорректировать положение лопастей, деформируя их в новое положение, возможно, интерполируя движение в течение короткого периода времени, чтобы сделать его менее резким.
Корректировать положение мяча легко, если оба клиента более или менее согласны (а затем вы можете снова проделать трюк с интерполяцией, чтобы сгладить его еще больше). Однако один клиент может увидеть почти промах, а другой — почти попадание. В этом случае, поскольку вы используете одноранговую модель, мы позволяем локальному клиенту совершать вызовы и объяснять, что случилось с оппонентом (в другом варианте у вас был бы центральный сервер, принимающий такие решения; это хорошо, чтобы избежать обмана). Вы не можете избежать неприятного скачка, если оба клиента не согласны, но, надеюсь, это должно происходить относительно редко и ненадолго, если только оно не совпадает со скачком пинга.
person
tucuxi
schedule
14.10.2016
m_flPredictionErrorTime
). Затем вы выбираете некоторое время, в течение которого будет происходить сглаживаниеcl_smoothtime
. Где-то рядом с кодом отображения вы вычисляете, сколько ошибок вы собираетесь отображатьerrorAmount = ( currentTimeMillis() - m_flPredictionErrorTime ) / cl_smoothtime
. Умножьте свой вектор различий на этиvOffset = m_vecPredictionError * errorAmount
и добавьте к вектору параметров (x, y, скорость, ...). Как толькоerrorAmount
больше 1, вы прекращаете его рассматривать (отображается полная дельта) - person Ivan   schedule 14.10.2016GetPredictionErrorSmoothingVector
из Исходный код SDK. Расскажите, как это сработало для вас, или задайте дополнительные вопросы. - person Ivan   schedule 14.10.2016