You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于C++与SFML的可移动小球与固定小球碰撞问题

问题分析与修复方案

你的碰撞处理逻辑存在三个核心问题:

  • 粒子已经嵌入重力源内部才处理速度,会导致持续触发碰撞判定
  • 法向速度分量计算错误,误用了分量相乘而非点积运算
  • 速度合成逻辑混乱,错误地将法向分量与切向单位向量直接相加

修复后的完整代码

void updatePhysics(GravitySource& gravitySource, float deltaTime)
{
    //Normal Vector (from particle to gravity source)
    float distanceX = gravitySource.getPos().x - pos.x;
    float distanceY = gravitySource.getPos().y - pos.y;

    //Distance between GravitySource and Particle
    float distance = std::sqrt(distanceX * distanceX + distanceY * distanceY);

    //Simplifying division to speed up calculations
    float inverseDistance = 1.f / distance;

    //Unit Normal Vector
    float normalizedX = inverseDistance * distanceX;
    float normalizedY = inverseDistance * distanceY;

    float inverseSquareDropOff = inverseDistance * inverseDistance;

    //Calculating Acceleration
    float accelerationX = normalizedX * gravitySource.getStrength() * inverseSquareDropOff * deltaTime;
    float accelerationY = normalizedY * gravitySource.getStrength() * inverseSquareDropOff * deltaTime;

    //Updating Velocity
    vel.x += accelerationX;
    vel.y += accelerationY;

    //Updating Position
    pos.x += vel.x;
    pos.y += vel.y;

    //Updating Render Position
    relPos.x = pos.x - radius;
    relPos.y = pos.y - radius;

    //Collision Handling
    float minDistance = radius + gravitySource.getRadius();
    if (distance <= minDistance)
    {
        // 1. 修正位置:将粒子从重力源内部推到碰撞边界外
        float overlap = minDistance - distance;
        pos.x -= normalizedX * overlap;
        pos.y -= normalizedY * overlap;
        relPos.x = pos.x - radius;
        relPos.y = pos.y - radius;

        // 2. 计算速度的法向分量(向量点积)
        float normalSpeed = vel.x * normalizedX + vel.y * normalizedY;

        // 3. 法向速度反向(重力源固定,质量视为无穷大,弹性碰撞下法向速度反转)
        // 可调整restitution值(0~1)模拟非完全弹性碰撞
        float restitution = 1.0f;
        float reversedNormalSpeed = -normalSpeed * restitution;

        // 4. 提取速度的切向分量(原速度减去法向分量)
        float tangentSpeedX = vel.x - normalizedX * normalSpeed;
        float tangentSpeedY = vel.y - normalizedY * normalSpeed;

        // 5. 合成新速度:切向分量 + 反转后的法向分量
        vel.x = tangentSpeedX + normalizedX * reversedNormalSpeed;
        vel.y = tangentSpeedY + normalizedY * reversedNormalSpeed;
    }
}

关键修复点说明

  1. 位置修正:计算粒子与重力源的重叠量,沿法向反方向移动粒子,确保它刚好贴在重力源表面,避免下一帧重复触发碰撞判定。
  2. 法向速度计算:通过向量点积vel · normal得到速度在法向上的标量大小,这是法向分量的正确计算方式。
  3. 速度合成:
    • 切向速度分量完全保留(无摩擦力时,碰撞不影响切向速度)
    • 法向速度分量反向(重力源固定不动,等效于质量无穷大,粒子碰撞后法向速度反转,恢复系数可调整弹性程度)

内容的提问来源于stack exchange,提问作者jaqubm

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 16:35:29