2014 dxdy logo

Научный форум dxdy

Математика, Физика, Computer Science, Machine Learning, LaTeX, Механика и Техника, Химия,
Биология и Медицина, Экономика и Финансовая Математика, Гуманитарные науки


Правила форума


Посмотреть правила форума



Начать новую тему Ответить на тему
 
 Расчёт скорости на заданом расстоянии (нетривиально)
Сообщение01.07.2017, 17:25 


01/07/17
6
Здравствуйте все!

Занимаюсь разработкой компьютерных игр. Встала необходимость сделать алгоритм расчёта энергии пули в шутере. Формально задача звучит так: Начальная скорость объекта (пули) задана ($V_0$). Известно расстояние, на котором произошла коллизия (попадание в монстра) ($S$). На пулю во время её полёта воздействует сила лобового сопротивления $F_d=C_x\frac{\rho V^2}{2} S$; ($C_x$, плотность воздуха и площадь лобового сечения заданы). Масса пули $m$ задана. Необходимо найти скорость $V$ в точке встречи.

Если решать в лоб, то задача тривиальная:
код: [ скачать ] [ спрятать ]
Используется синтаксис C#
        float s=0;
        float V=V0;
        float t=0;
        float dt = 0.0001F;
        while(s<S)
        {
            float Fd=Cx*(rho*Mathf.Pow(V,2)*0.5F)*S;
            float a=Fd/m;
            float dV=a*dt;

            V-=dV;
            s+=V*dt;
            t+=dt;
        }
 


Т.е., как вы видите, решается простым последовательным суммированием, после прохода цикла мы имеем $V$ в точке встречи. Всё бы ничего, но проблема в том что такой расчёт занимает очень много времени (по меркам компьютера, разумеется). Как можно это сделать короче, желательно не создавая цикла?

(Я попробовал находить скорость, составив и решив интегральное уравнение, но не получается его составить (да, в институте вышку проходил мимо, кто ж знал что так в жизни пригодится!) Не могу даже толком объяснить, что не получается. :-( Тут несколько неизвестных, и уравнение, вроде как, должно быть не одно, а система уравнений. Причём, непонятно как корректно подставить в эти уравнения формулу расчёта лобового сопротивления)

 Профиль  
                  
 
 Re: Расчёт скорости на заданом расстоянии (нетривиально)
Сообщение01.07.2017, 17:52 
Заслуженный участник
Аватара пользователя


22/06/12
2129
/dev/zero
В общем двумерном случае у вас есть плоскость выстрела, которая содержит линию, вдоль которой направлена начальная скорость, и эта плоскость перпендикулярна земле. Имеем плоскую задачу про сопротивление воздуха.

Для её решения можно использовать второй закон Ньютона в форме $m \mathbf{\dot v} = - k v \mathbf v + m \mathbf g$, потом к этому дифференциальному уравнению добавить начальные условия (радиус-вектор пули в момент выстрела и её вектор начальной скорости). Решив это дифференциальное уравнение, можно найти траекторию пули и прочие необходимые характеристики. Давайте определимся: либо мы решаем задачу численно, тогда вас стоит отослать, например, к книге Калиткина "Численные методы", либо мы пробуем решить задачу аналитически. Интегрированию, вроде, уравнение должно поддаваться, но я не пробовал.

-- 01.07.2017, 17:55 --

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

-- 01.07.2017, 18:09 --

Можно предложить и другой подход: на каждом отрезке времени $dt$ пересчиьывать кинетическую энергию по формуле
$$
m v\ \mathrm dv = m g\  \mathrm dh - k v (\mathbf v \cdot \mathrm d \mathbf s),
$$
где $\mathrm d \mathbf s$ -- элемент траектории пули. Это вектор, который состоит из компонент $(\mathrm d x, \mathrm dy)$, а каждая компонента вычисляется по формуле $\mathrm dx=v_x \ \mathrm dt$, аналогично для вертикальной компоненты. Здесь, однако, $\mathrm dy = \mathrm dh$ - изменение вертикальной координаты. Этим способом мы получим величину скорости в некоторый момент времени, но про траекторию сказать уже ничего не сможем. Впрочем, если оно не надо, то второй способ мне представляется более простым.

 Профиль  
                  
 
 Re: Расчёт скорости на заданом расстоянии (нетривиально)
Сообщение01.07.2017, 18:30 


01/07/17
6
2 StaticZero
Поясню некоторые детали. Нам не требуется определять положение траектории в рассматриваемой нами двумерной плоскости (движок игры уже сделал это за нас). Соответственно, начальное положение пули в глобальной системе координат в момент выстрела нам не важно. Действие силы тяжести также не учитывается (дистанции стрельбы в шутере невелики - десятки метров, и отклонение пули вниз, по моему предположению, будет невелико. Поэтому ради экономии вычислительных ресурсов мы имитируем полёт пули с помощью raycast. Эта функция строит "луч" из заданной точки в заданном направлении, и возвращает объект и точку, в которой "луч" пересёк первый на его пути объект). Поэтому, вероятно, добавлять ускорение $mg$ от силы тяготения тоже не нужно.

Стесняюсь собственной неграмотности, но в чём отличие численных методов решения такой задачи от аналитических? Насколько я понимаю, аналитический метод позволяет вывести (путём математических операций) решение в виде формулы, т.е., это, фактически, упрощение. А численный метод?

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

 Профиль  
                  
 
 Re: Расчёт скорости на заданом расстоянии (нетривиально)
Сообщение01.07.2017, 18:32 
Заслуженный участник
Аватара пользователя


23/07/08
10674
Crna Gora
Я ценю стремление к точности, но неужели геймер сможет заметить неправдоподобность модели, в которой скорость пули постоянна?

 Профиль  
                  
 
 Re: Расчёт скорости на заданом расстоянии (нетривиально)
Сообщение01.07.2017, 18:39 


01/07/17
6
StaticZero в сообщении #1230940 писал(а):
-- 01.07.2017, 18:09 --

Можно предложить и другой подход: на каждом отрезке времени $dt$ пересчиьывать кинетическую энергию по формуле
$$
m v\ \mathrm dv = m g\  \mathrm dh - k v (\mathbf v \cdot \mathrm d \mathbf s),
$$
где $\mathrm d \mathbf s$ -- элемент траектории пули. Это вектор, который состоит из компонент $(\mathrm d x, \mathrm dy)$, а каждая компонента вычисляется по формуле $\mathrm dx=v_x \ \mathrm dt$, аналогично для вертикальной компоненты. Здесь, однако, $\mathrm dy = \mathrm dh$ - изменение вертикальной координаты. Этим способом мы получим величину скорости в некоторый момент времени, но про траекторию сказать уже ничего не сможем. Впрочем, если оно не надо, то второй способ мне представляется более простым.

Этот вариант прокатил бы, если бы $dt$ было достаточно мало. Но он не работает нормально - скорость полёта пули велика (честные 500-700 м/с), а скорость обновления движка - фиксированные 60 тактов в секунду, т.е., $dt$ у нас 1/60-я секунды, большое время для реалистичной физики. В результате изменение энергии получается очень неплавным. (А ещё без дополнительных ухищрений мы получаем ситуацию когда пуля просто пролетит через противника, не задев его - на следующем кадре она оказывается уже далеко за ним :lol: )

 Профиль  
                  
 
 Re: Расчёт скорости на заданом расстоянии (нетривиально)
Сообщение01.07.2017, 18:43 
Заслуженный участник


05/08/14
1564
Daniil85 в сообщении #1230938 писал(а):
На пулю во время её полёта воздействует сила лобового сопротивления Fd=Cx*$\frac{\rho V^2}{2}$*S;

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

 Профиль  
                  
 
 Re: Расчёт скорости на заданом расстоянии (нетривиально)
Сообщение01.07.2017, 18:44 


01/07/17
6
svv в сообщении #1230946 писал(а):
Я ценю стремление к точности, но неужели геймер сможет заметить неправдоподобность модели, в которой скорость пули постоянна?

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

 Профиль  
                  
 
 Re: Расчёт скорости на заданом расстоянии (нетривиально)
Сообщение01.07.2017, 18:47 
Заслуженный участник
Аватара пользователя


23/07/08
10674
Crna Gora
Спасибо, понял.

 Профиль  
                  
 
 Re: Расчёт скорости на заданом расстоянии (нетривиально)
Сообщение01.07.2017, 18:55 


01/07/17
6
dsge в сообщении #1230952 писал(а):
Daniil85 в сообщении #1230938 писал(а):
На пулю во время её полёта воздействует сила лобового сопротивления Fd=Cx*$\frac{\rho V^2}{2}$*S;

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

Погуглил, интересный вариант. Спасибо, попробую поэкспериментировать.

 Профиль  
                  
 
 Re: Расчёт скорости на заданом расстоянии (нетривиально)
Сообщение01.07.2017, 19:39 
Заслуженный участник
Аватара пользователя


22/06/12
2129
/dev/zero
Daniil85 в сообщении #1230945 писал(а):
фактически, упрощение.

Вы знаете, вообще говоря, нет. Скажем, если интеграл уравнения имеет какой-нибудь такой вид, где функция выражается неявным образом, например
$$
\ln(x^2 + y^2) + \arctg xy = C,
$$
то, чтобы получать значения $y=y(x)$, нужно решить нелинейное уравнение численным методом. Чем это проще, чем решать исходное уравнение, которое привело к такому интегралу, сразу численно?

Daniil85 в сообщении #1230945 писал(а):
численных методов решения такой задачи от аналитических

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

Daniil85 в сообщении #1230945 писал(а):
Поэтому, вероятно, добавлять ускорение $mg$ от силы тяготения тоже не нужно.

Если так, то исходная задача становится и вовсе одномерной. Для того, чтобы её решить, введём замену переменных, убирая время из уравнения:$v(t) = u(s)$, где $s$ - координата вдоль линии выстрела. Соответственно, $\dot v=uu'$, и получаем закон изменения кинетической энергии в виде
$$ m u\ \mathrm du = - k u^2 \ \mathrm ds, $$
которое уже точно интегрируется в явном виде:
$$
\dfrac{\mathrm du}{u} = - \dfrac{k}{m}\ \mathrm ds,
$$
далее все шаблонно делается для ДУ с разделяющимися переменными. Результат - экспоненциальный спад скорости (и кинетической энергии) с расстоянием, пройденным в среде. На небольшом расстоянии от точки выстрела экспонента будет похожа на линейную функцию, что ещё больше упрощает ситуацию, при необходимости (скажем, если из геометрии ситуации ясно, что пуля попадёт в объект, находящийся на близком расстоянии). Небольшие расстояния здесь небольшие в том смысле, что они малы по сравнению с некоторым характерным расстоянием, на котором скорость спадает в $e$ раз.

Daniil85 в сообщении #1230948 писал(а):
Этот вариант прокатил бы, если бы $dt$ было достаточно мало. Но он не работает нормально - скорость полёта пули велика (честные 500-700 м/с), а скорость обновления движка - фиксированные 60 тактов в секунду, т.е., $dt$ у нас 1/60-я секунды, большое время для реалистичной физики.

Если коэффициент сопротивления среды велик, то да, будет существенная неприятность. Но не в этом случае, по крайней мере (см. выше).

 Профиль  
                  
 
 Re: Расчёт скорости на заданом расстоянии (нетривиально)
Сообщение01.07.2017, 21:40 


01/07/17
6
StaticZero в сообщении #1230963 писал(а):
получаем закон изменения кинетической энергии в виде
$$ m u\ \mathrm du = - k u^2 \ \mathrm ds, $$


Слушайте, это великолепно! Если б вы не напомнили мне, я бы не вспомнил что второй закон Ньютона пишется в таком виде! :-) А ведь эта запись это считай половина ответа. Ну и да, после замены переменной чтобы убрать время, всё становится решаемо как по учебнику.

В результате получается что
$u(s)=v_0\cdot e^{\frac{-k}{m}s}$


Соответственно, всё считается как надо! :D

Спасибо вам огромное!

 Профиль  
                  
 
 Re: Расчёт скорости на заданом расстоянии (нетривиально)
Сообщение01.07.2017, 21:42 
Заслуженный участник
Аватара пользователя


04/09/14
5012
ФТИ им. Иоффе СПб
StaticZero в сообщении #1230940 писал(а):
Для её решения можно использовать второй закон Ньютона в форме $m \mathbf{\dot v} = - k v \mathbf v + m \mathbf g$
Поскольку при горизонтальном выстреле вертикальная скорость мала, можно из нее выкинуть сопротивление воздуха, и получится
$$
\begin{align}
\dot{v}_x&=- k v_x^2\\
\dot{v}_y&=-mg,
\end{align}
$$
откуда мгновенно получим $v_x=\frac{v_{x0}}{v_{x0}kt+1},\; v_y=v_{y0}-gt$, что, по-моему, вполне сойдет, если мы стреляем более-менее горизонтально. При выстреле под углом имеет смысл оставить сопротивление вдоль линии выстрела и учесть член вида $\frac{mg}{v^2}$ как возмущение.

 Профиль  
                  
 
 Re: Расчёт скорости на заданом расстоянии (нетривиально)
Сообщение01.07.2017, 23:16 
Аватара пользователя


31/12/13
148
Daniil85
А как же зависимость $c_x(M)$? Придирчивые геймеры оценят! :D
Она, правда, заставит вернуться к численным методам, если её брать реальную, без упрощений.
А так, решение для постоянного к-та лобового сопротивления есть, например, в книжке "Средства поражения и боеприпасы". Совпадает с приведенным здесь: $V(x)=V_0e^{-Ax}$

 Профиль  
                  
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 13 ] 

Модераторы: Модераторы Математики, Супермодераторы



Кто сейчас на конференции

Сейчас этот форум просматривают: ihq.pl


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group