推荐用自定义结构体而非std::pair,因其语义清晰、扩展安全;SDL_Rect的交集检测仅支持整数且不返回交集区域;静态检测易漏判,需用扫掠检测或限速;圆矩碰撞应基于距离平方判断并统一坐标系。

矩形碰撞检测用 std::pair 还是自定义结构体?
直接用 std::pair<int int></int> 表示坐标或尺寸,写起来快但语义模糊,容易把 first/second 搞反。推荐定义轻量结构体,比如:
struct Rect { int x, y, w, h; };这样 rect1.x + rect1.w > rect2.x 一眼能看懂含义。别省这几行代码——后期加旋转、锚点或 AABB 扩展时,结构体改起来更安全。
SDL_Rect 和手写 AABB 判断逻辑有啥区别?
如果你用 SDL2,SDL_HasIntersection(&r1, &r2) 是最简方案,内部就是标准 AABB 判断;但注意它只支持整数坐标且不返回交集区域。自己写逻辑更可控:
bool intersects(const Rect& a, const Rect& b) {
return a.x < b.x + b.w && a.x + a.w > b.x &&
a.y < b.y + b.h && a.y + a.h > b.y;
}关键点:边界是否包含(即“相切算不算碰撞”)取决于你的游戏规则。多数情况用 < 和 >(开区间)更自然,避免帧间抖动导致误判。
为什么移动物体常漏判或重复触发?
这是最常见的坑:只检测当前帧的静态位置,没考虑运动轨迹。比如一个高速小球(宽高 2px)以每帧 10px 移动,可能直接“穿过”障碍物而没触发任何 intersects()。解决方法:
- 要么降低更新频率、提高采样精度(如子步进)
- 要么做扫掠检测(sweep test):用线段与矩形求交,判断移动路径是否穿越目标
- 或者简单粗暴——限制最大位移量,确保
max_speed <= min(rect_w, rect_h) / 2
圆形和矩形混检怎么写才不掉精度?
圆-矩碰撞本质是找圆心到矩形的最近点,再比对距离平方与半径平方:
bool circleRect(const Circle& c, const Rect& r) {
int dx = std::abs(c.x - (r.x + r.w/2));
int dy = std::abs(c.y - (r.y + r.h/2));
if (dx > r.w/2 + c.r || dy > r.h/2 + c.r) return false;
if (dx <= r.w/2 || dy <= r.h/2) return true;
return (dx - r.w/2)*(dx - r.w/2) + (dy - r.h/2)*(dy - r.h/2) <= c.r*c.r;
}注意:这里假设 Rect 坐标是左上角,圆心在 Circle{x,y,r};如果矩形用中心点表示,就不用加 r.w/2 偏移。最容易错的是忘记用距离平方避开了开方运算,也别在循环里反复算 c.r*c.r——提成局部常量。
真正麻烦的不是写对一个判断,而是统一所有物体的坐标系、更新时机和碰撞响应方式。比如角色跳跃时是否允许“脚踩平台边缘”、子弹是否忽略穿模、多个碰撞体同时触发时的顺序……这些得靠调试时打日志+可视化框线才能揪出来。


















