Difference between revisions of "QW physics air ru"

From QWiki
*>Sss
*>Sss
 
(13 intermediate revisions by the same user not shown)
Line 1: Line 1:
Физика QW: движение в воздухе, распрыг.
+
Предыдущая часть [http://wiki.quakeworld.nu/QW_physics_user_commands_ru]
  
При помощи команд 
 
  
  +forward
+
Физика QW: движение в воздухе, распрыг.
  +back
 
  +moveleft
 
  +moveright
 
  +moveup
 
  +movedown
 
  +speed
 
игрок задаёт значения forwardmove, sidemove, upmove.
 
  
 
Они определяются переменными
 
cl_sidespeed, cl_forwardspeed, cl_backspeed, cl_upspeed
 
 
Также команда +speed увеличивает их в 2 раза.
 
 
Если активны 2 противоположные команды (например, +forward и +back), то учитывается только та,
 
что была активирована раньше.
 
 
 
Значения forwardmove, sidemove, upmove передаются на сервер,
 
а также используется в клиенте для предсказания движения.
 
 
Код обработки движений игроков на сервере и на клиенте должен быть одинаковым.
 
 
У меня cl_forwardspeed 400 (ezquake default), а также при старте клиента выполняется строка
 
+mlook;wait;+speed;wait;
 
 
Поэтому при нажатии +forward
 
forwardmove = 2 * 400 = 800.
 
 
 
Движение рассчитывается в функции PM_PlayerMove.
 
 
 
 
Вероятно, в целях снижения трафика клиенты quake отрезают часть бит и
 
forwardmove = 800 почему-то превращается в 508 в PM_PlayerMove.
 
  
  
Line 45: Line 9:
 
Вычисляется т.н. вектор желаемой скорости.
 
Вычисляется т.н. вектор желаемой скорости.
 
В данном случае горизонтален и складывается только из 2-х компонент:
 
В данном случае горизонтален и складывается только из 2-х компонент:
  горизонтального вектора длины forwardmove, направленного вдоль направления взгляда по горизонтали,
+
горизонтального вектора длины forwardmove, направленного вдоль направления взгляда по горизонтали, и вектора длины sidemove, направленного вбок.
и вектора длины sidemove, направленного вбок.
 
 
upmove не учитывается.
 
upmove не учитывается.
  
 
В вертикальном направлении играет роль только гравитация. Она учитывается отдельно.
 
В вертикальном направлении играет роль только гравитация. Она учитывается отдельно.
  
Далее, если длина получившегося вектора превышает ограничение сервера,
+
Далее, если длина получившегося вектора превышает ограничение сервера V_max,
 
то его уменьшают до соответствующей длины.
 
то его уменьшают до соответствующей длины.
 
Это число равно 320 для обычного TDM и
 
Это число равно 320 для обычного TDM и
Line 75: Line 38:
 
accelspeed = accel * wishspeed * pm_frametime =  
 
accelspeed = accel * wishspeed * pm_frametime =  
 
             10 *320 * 0.014 = 44.8.
 
             10 *320 * 0.014 = 44.8.
(wishspeed  - это не wishspd)
+
wishspeed  - это не wishspd, а то что было до применения ограничения 30,
 +
т.е. при нормальных настройках это V_max.
 +
 
  
 
После выбирается минимальная из addspeed и accelspeed
 
После выбирается минимальная из addspeed и accelspeed
Line 100: Line 65:
 
зато важно, куда направлен его wishdir.
 
зато важно, куда направлен его wishdir.
  
 +
 +
Обозначим accel =  a и  pm_frametime = T.
 +
 +
T = 0.013, если работает 77fps физика
 +
и T = 0.014, если работает 72fps физика (TF2003 standard, old TDM standard).
  
  
 
Пусть угол между  горизонтальной скоростью v и wishdir равен gamma.
 
Пусть угол между  горизонтальной скоростью v и wishdir равен gamma.
 +
 +
[[Image:Wishdir.png]]
  
 
wishspd = min(wishspd, 30) = 30 при заданных выше условиях.
 
wishspd = min(wishspd, 30) = 30 при заданных выше условиях.
  
addspeed = wishspd - currentspeed = 30 -  v * cos(gamma)
+
addspeed = min(30 -  v * cos(gamma),  a * T * V_max)
  
конечное значение accelspeed >=0.
 
Нам надо увеличивать скорость, поэтому нужно обеспечивать
 
  
cos(gamma) > 0
+
График зависимости addspeed от cos(gamma):
addspeed = 30 - v * cos(gamma) > 0
 
  
При распрыге величина  accel * wishspeed * pm_frametime нам не важна,
 
т.к. мы не выходим на режим, где она актуальна.
 
Действительно, 44.8  > 30 -  v * cos(gamma), если cos(gamma) > -14.8/v,
 
т.е. если мы тормозим.
 
  
Итак, при распрыге accelspeed =  addspeed;
+
[[Image:Addspeed air fixed.png]]
  
  
Приращение скорости по модулю за один фрейм равно
 
dv_frame = addspeed * cos(gamma) = (30 - v * cos(gamma)) * cos(gamma).
 
  
График зависимости от cos(gamma) - перевёрнутая парабола.
+
Точка перелома -  cos(gamma_k).
 +
Здесь  30 - v * cos(gamma_k) ==  a * T * V_max,
  
Верхняя точка при  соs(gamma_best) = 15 / v;
+
cos(gamma_k) = (30 - a * T * V_max) / v.
  
dv_frame_best =  = (30 - v * 15 / v) * 15 / v = 225 / v.
+
Не забываем, что диапазон значений косинуса [-1; 1].
 +
Точка перелома выходит на границу допустимых значений при cos(gamma_k) = -1.
 +
При этом скорость v = 14.8. В TF это значение также мало.
 +
А как уже было выяснено скорость 30 достигается за один фрейм.
 +
Поэтому точка перелома находится всегда в допустимом диапазоне.
  
pm_frametime = 0.013, если работает 77fps физика
 
и pm_frametime = 0.014, если работает 72fps физика (TF2003 standard, old TDM standard).
 
  
В предельном случае скорость растёт по закону dv/dt = 225/(v * pm_frametime)
+
Рассмотрим, какой максимальный вклад в прирост скорости может дать
 +
горизонтальная часть графика.
  
Ускорение с 77fps физикой примерно на 7% больше, чем с 72fps.
+
Из теоремы косинусов
 +
v_new^2 = v^2 + (a*T*V_max)^2 +2*v*(a*T*V_Max)*cos(gamma).
  
v(t) ~ sqrt(t - t0).
+
Приращение тем больше, чем больше cos(gamma).
Подтверждено экспериментально, что игрок может преодолеть скорость sv_maxvelocity (2000)
+
Следовательно, на горизонтальной части лучшая точка - точка перелома,
 +
которая лежит также на наклонной части.
  
Теоретически её можно достичь распрыгом  за приблизительно 111 секунд с 77fps физикой.
+
Рассмотрим вклад, который может дать наклонная часть.
  
Игрок должен обеспечивать правильное направление wishdir.
+
v_new^2 = v^2 + (30 - v*cos(gamma))^2 + 2v*(30 - v*cos(gamma))*cos(gamma)
Это обеспечивается поворотом.
+
 
 +
Отсюда v_new^2 = v^2 + 30^2 - (v*cos(gamma))^2
 +
 
 +
Чем ближе к 0 cos(gamma), тем больше приращение скорости.
 +
 
 +
Точка перелома cos(gamma) < 0, если 30 < a * T * V_max,
 +
т.е. V_max > 30 / (a * T) = 230.8  при 77 fps  и 214 при 72 fps  физике.
 +
 
 +
Таким образом при распрыге в qw наибольшее ускорение получается при cos(gamma_best) == 0,
 +
кроме как у hwguy при 77fps (но не 72fps, как в TF2003!),
 +
где наилучшей точкой является точка излома cos(gamma_best) = (30 - a * T * V_max) / v.
 +
В этом исключительном случае 30 - a * T * V_max = 0.1, т.е при V > v_max=230
 +
0 < cos(gamma_best_hwg_77) < 4.34e-4.
 +
Поэтому этим исключительным случаем можно спокойно пренебречь.
 +
 
 +
При cos(gamma) = 0  v_new^2 = v^2 + 30^2
 +
 
 +
d(v^2)/dt = 30^2/T.
 +
 
 +
Идеальный разбег с прыжка на месте:
 +
v(t) = 30 * sqrt(t / T).
 +
 
 +
 
 +
dv/dt = 30^2/(2*v*T).
  
Правильная угловая скорость поворота
+
Ускорение при 77 fps больше, чем при 72fps на 7.7%.
omega = addspeed * sin(gamma) / v = (15 / v) * sqrt(1 - (15 / v)^2).
 
  
 +
За один фрейм угол поворота вектора скорости v delta_fi = arctg(30/v),
 +
т.е. угловая скорость поворота вектора v равна omega = (1/T)*arctg(30/v).
 +
При v>>30 omega = 30 / (vT).
 
С ростом скорости надо всё медленнее поворачиваться.
 
С ростом скорости надо всё медленнее поворачиваться.
 +
 +
Подтверждено экспериментально, что переменная sv_maxvelocity (2000) не ограничивает
 +
скорость игрока.
 +
 +
Теоретически её можно достичь распрыгом  за приблизительно 58 секунд с 77fps физикой.
 +
 +
Игрок должен обеспечивать правильное направление wishdir.
 +
Это обеспечивается поворотом и правильным нажатием клавиш.
  
 
Комментарии и поправки приветствуются.
 
Комментарии и поправки приветствуются.
 +
 +
Движение на земле рассмотрено здесь: [http://wiki.quakeworld.nu/QW_physics_ground_ru]

Latest revision as of 08:42, 28 February 2010

Предыдущая часть [1]


Физика QW: движение в воздухе, распрыг.


Рассмотрим движение игрока в воздухе. Вычисляется т.н. вектор желаемой скорости. В данном случае горизонтален и складывается только из 2-х компонент: горизонтального вектора длины forwardmove, направленного вдоль направления взгляда по горизонтали, и вектора длины sidemove, направленного вбок. upmove не учитывается.

В вертикальном направлении играет роль только гравитация. Она учитывается отдельно.

Далее, если длина получившегося вектора превышает ограничение сервера V_max, то его уменьшают до соответствующей длины. Это число равно 320 для обычного TDM и меняется от 230 до 450 в зависимости от класса игрока в TF.

Далее используются единичный вектор желаемого направления и значение желаемой скорости: мы попали в функцию PM_PlayerAccelerate().

Здесь значение желаемой скорости сразу ограничивается числом 30: wishspd = min(wishspd, 30);

Находим проекцию текущей скорости на желаемое направление: currentspeed = DotProduct (pmove.velocity, wishdir);

Вычисляем разницу между желаемой скоростью и проекцией теущей скорости. Если получается отрицательное число, то скорость не меняется. addspeed = wishspd - currentspeed; if (addspeed <= 0) return;


Далее вычисляется величина accelspeed = accel * wishspeed * pm_frametime =

            10 *320 * 0.014 = 44.8.

wishspeed - это не wishspd, а то что было до применения ограничения 30, т.е. при нормальных настройках это V_max.


После выбирается минимальная из addspeed и accelspeed accelspeed = min(accelspeed, addspeed);

Добавляем к вектору скорости вектор с полученной длиной и направлением wishdir VectorMA(pmove.velocity, accelspeed, wishdir, pmove.velocity);


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

Если у игрока нулевая скорость, то выполнив +forward, он приобретёт сразу скорость 30, направленную горизонтально вперёд.

Теперь рассмотрим распрыг. Скорость сразу будем считать большей, чем ограничение сервера (320 в TDM), т.к. её можно достигнуть ещё на земле. Разумеется, считаем, что игрок не устанавливал значения cl_sidespeed, cl_forwardspeed, cl_backspeed слишком маленькими.

Замечательным фактом является то, что в сущности, не важно, куда смотрит игрок, зато важно, куда направлен его wishdir.


Обозначим accel = a и pm_frametime = T.

T = 0.013, если работает 77fps физика и T = 0.014, если работает 72fps физика (TF2003 standard, old TDM standard).


Пусть угол между горизонтальной скоростью v и wishdir равен gamma.

Wishdir.png

wishspd = min(wishspd, 30) = 30 при заданных выше условиях.

addspeed = min(30 - v * cos(gamma), a * T * V_max)


График зависимости addspeed от cos(gamma):


Addspeed air fixed.png


Точка перелома - cos(gamma_k). Здесь 30 - v * cos(gamma_k) == a * T * V_max,

cos(gamma_k) = (30 - a * T * V_max) / v.

Не забываем, что диапазон значений косинуса [-1; 1]. Точка перелома выходит на границу допустимых значений при cos(gamma_k) = -1. При этом скорость v = 14.8. В TF это значение также мало. А как уже было выяснено скорость 30 достигается за один фрейм. Поэтому точка перелома находится всегда в допустимом диапазоне.


Рассмотрим, какой максимальный вклад в прирост скорости может дать горизонтальная часть графика.

Из теоремы косинусов v_new^2 = v^2 + (a*T*V_max)^2 +2*v*(a*T*V_Max)*cos(gamma).

Приращение тем больше, чем больше cos(gamma). Следовательно, на горизонтальной части лучшая точка - точка перелома, которая лежит также на наклонной части.

Рассмотрим вклад, который может дать наклонная часть.

v_new^2 = v^2 + (30 - v*cos(gamma))^2 + 2v*(30 - v*cos(gamma))*cos(gamma)

Отсюда v_new^2 = v^2 + 30^2 - (v*cos(gamma))^2

Чем ближе к 0 cos(gamma), тем больше приращение скорости.

Точка перелома cos(gamma) < 0, если 30 < a * T * V_max, т.е. V_max > 30 / (a * T) = 230.8 при 77 fps и 214 при 72 fps физике.

Таким образом при распрыге в qw наибольшее ускорение получается при cos(gamma_best) == 0, кроме как у hwguy при 77fps (но не 72fps, как в TF2003!), где наилучшей точкой является точка излома cos(gamma_best) = (30 - a * T * V_max) / v. В этом исключительном случае 30 - a * T * V_max = 0.1, т.е при V > v_max=230

0 < cos(gamma_best_hwg_77) < 4.34e-4.

Поэтому этим исключительным случаем можно спокойно пренебречь.

При cos(gamma) = 0 v_new^2 = v^2 + 30^2

d(v^2)/dt = 30^2/T.

Идеальный разбег с прыжка на месте: v(t) = 30 * sqrt(t / T).


dv/dt = 30^2/(2*v*T).

Ускорение при 77 fps больше, чем при 72fps на 7.7%.

За один фрейм угол поворота вектора скорости v delta_fi = arctg(30/v), т.е. угловая скорость поворота вектора v равна omega = (1/T)*arctg(30/v). При v>>30 omega = 30 / (vT). С ростом скорости надо всё медленнее поворачиваться.

Подтверждено экспериментально, что переменная sv_maxvelocity (2000) не ограничивает скорость игрока.

Теоретически её можно достичь распрыгом за приблизительно 58 секунд с 77fps физикой.

Игрок должен обеспечивать правильное направление wishdir. Это обеспечивается поворотом и правильным нажатием клавиш.

Комментарии и поправки приветствуются.

Движение на земле рассмотрено здесь: [2]