圆形分离异常求助:半径变化导致位置偏移
修复圆形半径变化时的偏移问题,实现同步分离效果
问题根源分析
原代码里的cx、cy计算是基于当前两圆心的距离按半径比例分割,但当其中一个圆的半径变化时,maxDist(两半径之和)和当前distance的差值会动态改变,原逻辑的修正量计算绕了弯路,导致位置偏移。核心问题是没有直接基于需要修正的重叠距离来分配两个圆的移动量,而是依赖了当前位置的中间点,这在半径动态变化时容易出错。
修正后的实现思路
我们需要直接计算两个圆需要分开的总距离,然后按它们的半径比例来分配各自的移动量,这样不管半径怎么变,都能保证最终两圆心距离刚好等于半径之和,且同步平滑分离:
- 计算两圆心的方向向量并归一化
- 计算重叠量:
overlap = 两半径之和 - 当前距离(也就是需要分开的总距离) - 按半径比例分配移动距离:小圆移动的比例更大,大圆移动比例更小(符合物理直觉,也能保证同步分离)
- 用动画常数平滑移动到目标位置
修正后的代码
CollisionHandler.pushApart = function(cell, check) { var x = check.x - cell.x; var y = check.y - cell.y; var distance = Math.hypot(x, y); var cSz = Blob.getSize(cell.mass); var chSz = Blob.getSize(check.mass); var maxDist = cSz + chSz; var boosting = Math.abs(cell.move.x) > 2 || Math.abs(cell.move.y) > 2 || Math.abs(check.move.x) > 2 || Math.abs(check.move.y) > 2; // 只有在重叠、非加速且两圆心不重合时处理分离 if (distance < maxDist && !boosting && distance > 0) { // 归一化方向向量(从cell指向check) var dirX = x / distance; var dirY = y / distance; // 计算需要分开的总重叠距离 var overlap = maxDist - distance; // 按对方半径占总半径的比例分配移动量:小的圆移动更多,大的圆移动更少 var cellMoveDist = overlap * (chSz / (cSz + chSz)); var checkMoveDist = overlap * (cSz / (cSz + chSz)); // 应用平滑移动,两个圆向相反方向远离 cell.x -= dirX * cellMoveDist * animationConstant; cell.y -= dirY * cellMoveDist * animationConstant; check.x += dirX * checkMoveDist * animationConstant; check.y += dirY * checkMoveDist * animationConstant; } };
代码说明
- 新增
distance>0判断:避免当两个圆完全重合时出现除以0的错误 - 直接计算
overlap:明确需要分离的总距离,逻辑更清晰易懂 - 按对方半径比例分配移动量:保证两个圆同步分离,不会出现偏移,比如大圆和小圆重叠时,小圆移动幅度更大,符合物理逻辑
- 方向处理:cell向远离check的方向移动,check向远离cell的方向移动,确保两者始终保持正确的间距
这样修改后,不管其中一个圆的半径怎么变化,两个圆都会基于当前的半径和位置,平滑同步地分离到正确的位置,不会再出现偏移问题啦。
内容的提问来源于stack exchange,提问作者badboy24
相关产品推荐
相关产品推荐

