<p>不能直接用 std::abs(p1 - p2) 判断AABB碰撞,因为碰撞判定需检查x、y方向是否同时重叠,而非计算距离;正确逻辑是:rect1.max_x > rect2.min_x && rect1.min_x < rect2.max_x && rect1.max_y > rect2.min_y && rect1.min_y < rect2.max_y。</p>

为什么不能直接用 std::abs(p1 - p2) 判圆碰撞
因为这只能处理点与点、点与圆,而真实 2D 碰撞需要区分形状:矩形(AABB)、圆形、旋转矩形(OBB)甚至多边形。最常踩的坑是把 sf::FloatRect.contains() 或 SDL_HasIntersection() 当成万能解——它们只支持轴对齐矩形,一旦对象旋转就失效。
实际项目里,90% 的轻量需求只需要 AABB + 圆形检测,其余用近似(比如把旋转矩形用更大 AABB 包围)换性能。别一上来就写分离轴定理(SAT)。
AABB 碰撞检测怎么写才不漏判
核心是“投影重叠”:两个矩形在 x 和 y 轴上的投影都重叠,才算相交。漏判常见于边界处理——比如用 <= 而不是 < 导致贴边不算碰撞,或没考虑坐标系原点(左上 or 左下)。
- 用
min_x/max_x存储而非x/y/width/height,避免每次计算x + width - 检测逻辑必须是:
rect1.max_x > rect2.min_x && rect1.min_x rect2.min_y && rect1.min_y - 如果图形库返回的是
sf::FloatRect,注意它的left/top是左上角,width/height为正,直接转min_x = left, max_x = left + width
Circle 和 AABB 混合检测怎么避免开方
圆与矩形碰撞不是简单算圆心到矩形中心距离。正确做法是:求圆心到矩形的最近点,再比对该点与圆心距离是否 ≤ 半径。关键优化是全程用平方距离,跳过 sqrt()。
立即学习“C++免费学习笔记(深入)”;
实操步骤:
- 将圆心
cx, cyclamp 到矩形[min_x, max_x] × [min_y, max_y]范围内,得到最近点closest_x, closest_y - 计算平方距离:
dx = cx - closest_x; dy = cy - closest_y; dist_sq = dx*dx + dy*dy - 比较
dist_sq
注意:clamp 用 std::max(min_x, std::min(cx, max_x)),别手写 if,否则分支预测失败影响性能。
要不要支持 std::vector<Point> 多边形碰撞
除非你在做物理引擎或地图编辑器,否则真没必要。多边形碰撞检测(如射线法、SAT)代码量陡增,且容易因浮点误差导致“穿模”。更现实的做法是:
- 用 4–8 个点近似圆形(如正八边形),走 SAT;但多数情况一个
Circle就够了 - 对不规则物体,用多个
AABB组合(hitbox 分层),比如角色身体用一个大矩形,拳头单独加一个小矩形 - 若必须支持任意多边形,优先用
Clipper2库做布尔运算,而不是自己实现交集判断
真正难的不是算法本身,而是如何让碰撞结果稳定反馈给游戏逻辑——比如一次移动中穿透了两个物体,该通知哪个?这需要额外的时间步长控制和碰撞顺序管理,已超出“简单库”范畴。


















