2D物理效果代码实现思路(5)直线运动

By pocaster

方向、速度、时间、加速度与像素/现实比例解析


一、方向(Direction)

定义
  • 方向是物体移动或面对的角度或向量,通常用 归一化向量(Normalized Vector) 表示。
  • 方向可以源自玩家输入(如键盘、手柄)、AI 逻辑或物理引擎。
游戏中的应用
  1. 向量表示:用 (x, y) 表示二维方向,或用 (x, y, z) 表示三维方向。
    Vector2 direction = Vector2(1, 0); // 向右移动
    direction = direction.Normalize(); // 归一化向量(确保长度为1)
    
  2. 输入转换为方向
    // 玩家通过 WASD 控制方向
    Vector2 inputDirection = Vector2(
        Input.GetAxis("Horizontal"), // 水平轴(A/D 或 ←/→)
        Input.GetAxis("Vertical")    // 垂直轴(W/S 或 ↑/↓)
    ).Normalized(); 
    
  3. 旋转朝向目标
    // 计算旋转角度(如转向鼠标位置)
    Vector2 mousePos = GetMousePosition();
    Vector2 toMouse = mousePos - player.position;
    float angle = atan2(toMouse.y, toMouse.x); // 弧度角
    player.SetRotation(angle);
    

二、速度(Velocity)

定义
  • 速度是物体在单位时间内的位移量,通常用 向量(Vector) 表示,包含方向和大小。
  • 速度的单位可以是 像素/秒米/秒,具体取决于游戏的坐标系设计。
游戏中的应用
  1. 基于方向的移动
    Vector2 direction = player.GetDirection(); // 归一化方向
    float speed = 300.0f; // 单位:像素/秒
    player.velocity = direction * speed; // 速度 = 方向 × 速率
    
  2. 速度更新位置
    void Update(float deltaTime) {
        player.position += player.velocity * deltaTime;
    }
    
  3. 摩擦力模拟
    float friction = 0.9f; // 摩擦力系数(每秒速度保留90%)
    player.velocity *= pow(friction, deltaTime); // 随时间衰减
    

三、时间(Time)

定义
  • 时间是游戏逻辑的推进基准,通过 DeltaTime 实现帧率无关的更新。
  • DeltaTime 用于缩放速度和加速度的实时效果。
游戏中的应用
  1. 帧率无关性
    // 速度 × DeltaTime → 距离增量
    player.position += velocity * deltaTime;
    
  2. 定时器和延迟
    float cooldownTimer = 2.0f; // 冷却时间2秒
    cooldownTimer -= deltaTime;
    if (cooldownTimer <= 0) {
        FireProjectile();
        cooldownTimer = 2.0f;
    }
    

四、加速度(Acceleration)

定义
  • 加速度是速度在单位时间内的变化率,由外力(如重力、推力)驱动。
  • 加速度的单位通常是 像素/秒²米/秒²
游戏中的应用
  1. 速度的更新
    Vector2 acceleration = Vector2(0, 9.8f); // 模拟重力
    player.velocity += acceleration * deltaTime;
    player.position += player.velocity * deltaTime;
    
  2. 玩家控制的加速度
    float accelerationRate = 500.0f; // 加速度:500像素/秒²
    Vector2 inputDirection = GetInputDirection();
    player.velocity += inputDirection * accelerationRate * deltaTime;
    
  3. 速度限制
    float maxSpeed = 600.0f; // 限制最大速度
    if (player.velocity.Magnitude() > maxSpeed) {
        player.velocity = player.velocity.Normalized() * maxSpeed;
    }
    

五、像素与现实比例(Pixel-to-Reality Scale)

定义
  • 像素与现实比例是游戏中虚拟单位(像素)与现实单位(米)的换算关系。
  • 常见的比例如 1米 = 64像素,用于保持物理模拟的一致性。
游戏中的应用
  1. 物理引擎的缩放系数
    const float PIXELS_PER_METER = 64.0f;
    Vector2 gravity = Vector2(0, 9.8f) * PIXELS_PER_METER; // 重力加速度(像素/秒²)
    
  2. 单位转换
    // 角色跳跃高度设定为2米
    float jumpHeightMeters = 2.0f;
    float jumpHeightPixels = jumpHeightMeters * PIXELS_PER_METER;
    
    // 速度转换(1米/秒 → 64像素/秒)
    float speedMetersPerSec = 5.0f;
    float speedPixelsPerSec = speedMetersPerSec * PIXELS_PER_METER;
    
  3. 跨系统一致性
    • 物理引擎(如 Box2D):设置 PIXELS_PER_METER 与引擎的 meter 单位对齐。
    • 渲染系统:物体尺寸按此比例设计(如角色高度为 1.7米 → 1.7 * 64 = 109像素)。

六、完整代码示例

// 定义全局常量
const float PIXELS_PER_METER = 64.0f;
const float GRAVITY = 9.8f * PIXELS_PER_METER; // 像素/秒²

class Player {
public:
    Vector2 position;
    Vector2 velocity;
    Vector2 direction;

    void Update(float deltaTime) {
        // 输入控制
        Vector2 inputDirection = GetInputDirection().Normalized();

        // 应用加速度
        float acceleration = 500.0f; // 像素/秒²
        velocity += inputDirection * acceleration * deltaTime;

        // 应用重力
        velocity.y += GRAVITY * deltaTime;

        // 限制速度(最大水平速度600像素/秒)
        float maxSpeed = 600.0f;
        if (velocity.Magnitude() > maxSpeed) {
            velocity = velocity.Normalized() * maxSpeed;
        }

        // 更新位置
        position += velocity * deltaTime;
    }

    void Jump() {
        if (IsGrounded()) {
            velocity.y = -800.0f; // 跳跃初速度(800像素/秒)
        }
    }
};

七、常见问题及解决方案

  1. 速度过快导致穿透
    • 使用碰撞检测的 连续碰撞检测(CCD) 或限制每帧移动的最大距离。
  2. 单位混乱引发的Bug
    • 始终统一使用 像素,并用比例系数转换。
  3. 非物理直觉的参数
    • 如跳跃高度与速度的匹配,通过物理公式验证: \(v = \sqrt{2gh} \quad \text{(初速度公式)}\) 例如:h = 2米 → v = sqrt(2*9.8*2) ≈ 6.26米/秒 → 6.26 * PIXELS_PER_METER ≈ 400像素/秒

总结

方向、速度、时间、加速度和像素/现实比例是构建游戏物理系统的基石。通过合理的单位定义和数学运算,可以实现真实的运动效果。开发者需要:

  1. 明确物理概念的数学表达
  2. 统一单位和比例
  3. 优化参数和算法以提高性能和稳定性。
Tags: Gamedev Public