Движение в 2D: две независимые оси
Главный секрет полёта снаряда: по горизонтали и по вертикали тело движется независимо.
Принцип независимости движений — движение по перпендикулярным осям можно считать раздельно: по каждой оси действует своя кинематика.
Раскладываем скорость на компоненты
Брошенный под углом $\alpha$ со скоростью $v_0$ мяч имеет две составляющие скорости:
$$v_{0x} = v_0 \cos\alpha, \qquad v_{0y} = v_0 \sin\alpha.$$
По горизонтали (если нет сопротивления) ускорения нет — скорость $v_x$ постоянна. По вертикали действует гравитация, и работает уже знакомая кинематика с $a = -g$. Эти два движения не мешают друг другу: время полёта определяется вертикалью, а дальность — произведением горизонтальной скорости на это время. В этом вся прелесть — задачу 2D мы свели к двум независимым задачам 1D.
Симулируем бросок под углом
Бросим мяч со скоростью $20$ м/с под углом $45°$ и напечатаем траекторию — пары $(x, y)$ — пока мяч не упадёт на землю ($y \lt 0$).
import math
v0, ang = 20.0, math.radians(45)
vx = v0 * math.cos(ang)
vy = v0 * math.sin(ang)
x, y, dt, g = 0.0, 0.0, 0.1, 9.8
while True:
print(f"x={x:6.2f} y={y:6.2f}")
vy = vy - g * dt
x = x + vx * dt
y = y + vy * dt
if y < 0:
break
print(f"дальность ~ {x:.2f} м")
Вывод:
x= 0.00 y= 0.00 x= 1.41 y= 1.32 x= 2.83 y= 2.53 x= 4.24 y= 3.65 x= 5.66 y= 4.68 x= 7.07 y= 5.60 x= 8.49 y= 6.43 x= 9.90 y= 7.16 x= 11.31 y= 7.79 x= 12.73 y= 8.32 x= 14.14 y= 8.75 x= 15.56 y= 9.09 x= 16.97 y= 9.33 x= 18.38 y= 9.47 x= 19.80 y= 9.51 x= 21.21 y= 9.45 x= 22.63 y= 9.30 x= 24.04 y= 9.05 x= 25.46 y= 8.70 x= 26.87 y= 8.25 x= 28.28 y= 7.70 x= 29.70 y= 7.06 x= 31.11 y= 6.32 x= 32.53 y= 5.48 x= 33.94 y= 4.54 x= 35.36 y= 3.51 x= 36.77 y= 2.37 x= 38.18 y= 1.14 дальность ~ 39.60 м
Траектория — симметричная парабола: мяч поднимается до $\approx 9.74$ м, потом падает. Горизонтальная координата растёт строго равномерно на $1.41$ м за шаг ($v_x \Delta t$), что подтверждает: по горизонтали движение равномерное. Аналитическая дальность $R = \frac{v_0^2 \sin 2\alpha}{g} = \frac{400 \cdot 1}{9.8} \approx 40.82$ м; наша грубая симуляция дала $39.60$ — отлично сходится.
Как работает под капотом
В коде мы храним четыре числа: $x, y, v_x, v_y$. Каждая ось обновляется по своей формуле, и они никак не связаны между собой через переменные. Именно так устроен любой 2D-движок: вектор скорости — это просто пара чисел, и пока силы можно разложить на компоненты, оси считаются по отдельности. Связь между осями появляется только когда сила зависит от направления движения — например, при сопротивлении воздуха, которое тянет тело против полного вектора скорости. Тогда $v_x$ и $v_y$ перестают быть независимыми, и аналитической формулы дальности уже нет (мы увидим это в разделе про снаряды).
Частые ошибки
- Путать синус и косинус. Горизонталь — это $\cos\alpha$, вертикаль — $\sin\alpha$. Перепутаешь — мяч полетит не туда.
- Забыть перевести градусы в радианы.
math.cosждёт радианы; для $45°$ нужноmath.radians(45). - Думать, что оси всегда независимы. Сопротивление воздуха связывает их, и принцип независимости перестаёт работать.
Итог
- Скорость раскладывается: $v_x = v_0\cos\alpha$, $v_y = v_0\sin\alpha$.
- Без сопротивления оси движутся независимо: горизонталь — равномерно, вертикаль — с $g$.
- Симуляция по двум осям воспроизводит параболу и сходится к $R=\frac{v_0^2\sin 2\alpha}{g}$.
- Сопротивление воздуха связывает оси и ломает аналитику.