土法炼钢兴趣小组的算法知识备份

游戏中的数学 (6) - 运动学基础

目录

引言

运动学 (Kinematics) 关注的是物体如何移动,而不关心为什么移动(那是动力学的事)。 在游戏中,这通常意味着根据速度和加速度更新物体的位置。

1. 基础公式

最简单的物理更新循环: \[ Position_{new} = Position_{old} + Velocity \times \Delta t \] \[ Velocity_{new} = Velocity_{old} + Acceleration \times \Delta t \]

这对应了物理学中的匀加速直线运动公式: \[ s = v_0 t + \frac{1}{2} a t^2 \]

2. 积分器 (Integrators)

在计算机中,时间不是连续的,而是离散的帧 (\(\Delta t\))。我们需要用数值积分来近似计算位置。

Integration Methods

显式欧拉积分 (Explicit Euler)

这是最简单也是最常用的方法(如 Unity 的 Rigidbody 默认行为)。

void Update(float dt) {
    velocity += acceleration * dt;
    position += velocity * dt;
}

韦尔莱积分 (Verlet Integration)

这种方法不显式存储速度,而是通过当前位置和上一帧位置来推导速度。 \[ x_{new} = 2x_{current} - x_{old} + a \cdot \Delta t^2 \]

void Update(float dt) {
    Vector3 temp = position;
    position = 2 * position - oldPosition + acceleration * dt * dt;
    oldPosition = temp;
}

3. 抛物线运动 (Projectile Motion)

在射击游戏中,我们经常需要预测炮弹的落点。 如果不考虑空气阻力,水平方向是匀速运动,垂直方向是匀加速运动(重力)。

\[ x(t) = x_0 + v_{x0} t \] \[ y(t) = y_0 + v_{y0} t - \frac{1}{2} g t^2 \]

瞄准算法

已知起点 \(P\) 和目标 \(T\),以及炮弹速度 \(v\),求发射角度 \(\theta\)。 这是一个经典的物理问题。通过消除时间变量 \(t\),我们可以得到一个关于 \(\tan \theta\) 的一元二次方程。

代码实现:

float? CalculateLaunchAngle(Vector3 start, Vector3 target, float v, float g = 9.81f) {
    float x = Vector3.Distance(new Vector3(start.x, 0, start.z), new Vector3(target.x, 0, target.z));
    float y = target.y - start.y;
    
    float v2 = v * v;
    float v4 = v2 * v2;
    float term = v4 - g * (g * x * x + 2 * y * v2);
    
    if (term < 0) return null; // 目标太远,打不到
    
    // 通常有两个解:高抛和低抛。这里返回低抛角度(直射)。
    float tanTheta = (v2 - Mathf.Sqrt(term)) / (g * x);
    return Mathf.Atan(tanTheta) * Mathf.Rad2Deg;
}

总结


< 上一篇: 相交检测 | 回到目录 | 下一篇: 碰撞响应 >


By .