圆、矩形、线段碰撞检测
// 矩形和圆形碰撞检测 bool IsCirlceCollisionRect(float circleXPos, float circleYPos, float radius, float rectX, float rectY, float rectW, float rectH) { float arcR = radius; float arcOx = circleXPos; float arcOy = circleYPos; //分别判断矩形4个顶点与圆心的距离是否<=圆半径;如果<=,说明碰撞成功 if(((rectX-arcOx) * (rectX-arcOx) + (rectY-arcOy) * (rectY-arcOy)) <= arcR * arcR) return true; if(((rectX+rectW-arcOx) * (rectX+rectW-arcOx) + (rectY-arcOy) * (rectY-arcOy)) <= arcR * arcR) return true; if(((rectX-arcOx) * (rectX-arcOx) + (rectY+rectH-arcOy) * (rectY+rectH-arcOy)) <= arcR * arcR) return true; if(((rectX+rectW-arcOx) * (rectX+rectW-arcOx) + (rectY+rectH-arcOy) * (rectY+rectH-arcOy)) <= arcR * arcR) return true; //判断当圆心的Y坐标进入矩形内时X的位置,如果X在(rectX-arcR)到(rectX+rectW+arcR)这个范围内,则碰撞成功 float minDisX = 0; if(arcOy >= rectY && arcOy <= rectY + rectH) { if(arcOx < rectX) minDisX = rectX - arcOx; else if(arcOx > rectX + rectW) minDisX = arcOx - rectX - rectW; else return true; if(minDisX <= arcR) return true; } //判断当圆心的X坐标进入矩形内时Y的位置,如果X在(rectY-arcR)到(rectY+rectH+arcR)这个范围内,则碰撞成功 float minDisY = 0; if(arcOx >= rectX && arcOx <= rectX + rectW) { if(arcOy < rectY) minDisY = rectY - arcOy; else if(arcOy > rectY + rectH) minDisY = arcOy - rectY - rectH; else return true; if(minDisY <= arcR) return true; } return false; } // 线段和线段碰撞检测 bool IsLineCollisionLine(cocos2d::CCPoint p1, cocos2d::CCPoint p2, cocos2d::CCPoint p3, cocos2d::CCPoint p4) { float x1 = p1.x, x2 = p2.x, x3 = p3.x, x4 = p4.x; float y1 = p1.y, y2 = p2.y, y3 = p3.y, y4 = p4.y; float d = (x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4); // If d is zero, there is no intersection if (d == 0) return false; // Get the x and y float pre = (x1*y2 - y1*x2), post = (x3*y4 - y3*x4); float x = ( pre * (x3 - x4) - (x1 - x2) * post ) / d; float y = ( pre * (y3 - y4) - (y1 - y2) * post ) / d; // Check if the x and y coordinates are within both lines if ( x < MIN(x1, x2) || x > MAX(x1, x2) || x < MIN(x3, x4) || x > MAX(x3, x4) ) return false; if ( y < MIN(y1, y2) || y > MAX(y1, y2) || y < MIN(y3, y4) || y > MAX(y3, y4) ) return false; return true; } static float mult(cocos2d::CCPoint a, cocos2d::CCPoint b, cocos2d::CCPoint c) { return (a.x-c.x)*(b.y-c.y)-(b.x-c.x)*(a.y-c.y); } bool IsLineCollisionLine2(cocos2d::CCPoint aa, cocos2d::CCPoint bb, cocos2d::CCPoint cc, cocos2d::CCPoint dd) { if ( MAX(aa.x, bb.x)<MIN(cc.x, dd.x) ) return false; if ( MAX(aa.y, bb.y)<MIN(cc.y, dd.y) ) return false; if ( MAX(cc.x, dd.x)<MIN(aa.x, bb.x) ) return false; if ( MAX(cc.y, dd.y)<MIN(aa.y, bb.y) ) return false; if (mult(cc, bb, aa)*mult(bb, dd, aa)<0.0001f) return false; if (mult(aa, dd, cc)*mult(dd, bb, cc)<0.0001f) return false; return true; } // 线段和矩形碰撞检测 bool IsLineCollisionRect(cocos2d::CCPoint lineStartPoint, cocos2d::CCPoint lineEndPoint, cocos2d::CCPoint rectleftBottomPoint, float width, float height) { // 因为这个方法专门进行射线光束的碰撞检测,所以暂不进行线段在矩形内的碰撞检测 cocos2d::CCPoint leftLineStartPoint = rectleftBottomPoint; cocos2d::CCPoint leftLineEndPoint = cocos2d::CCPoint(leftLineStartPoint.x, leftLineStartPoint.y+height); cocos2d::CCPoint rightLineStartPoint= cocos2d::CCPoint(leftLineStartPoint.x+width, leftLineStartPoint.y); cocos2d::CCPoint rightLineEndPoint = cocos2d::CCPoint(leftLineStartPoint.x+width, leftLineStartPoint.y+height); cocos2d::CCPoint topLineStartPoint = cocos2d::CCPoint(leftLineStartPoint.x, leftLineStartPoint.y+height); cocos2d::CCPoint topLineEndPoint = cocos2d::CCPoint(leftLineStartPoint.x+width, leftLineStartPoint.y+height); cocos2d::CCPoint bottomLineStartPoint= cocos2d::CCPoint(leftLineStartPoint.x, leftLineStartPoint.y); cocos2d::CCPoint bottomLineEndPoint = cocos2d::CCPoint(leftLineStartPoint.x+width, leftLineStartPoint.y); cocos2d::CCPoint leftBottomLineStartPoint= rectleftBottomPoint; cocos2d::CCPoint rightTopLineEndPoint = rightLineEndPoint; cocos2d::CCPoint leftTopLineStartPoint = leftLineEndPoint; cocos2d::CCPoint rightBottomLineEndPoint = rightLineStartPoint; do { if (IsLineCollisionLine2(lineStartPoint, lineEndPoint, leftLineStartPoint, leftLineEndPoint)) break; if (IsLineCollisionLine2(lineStartPoint, lineEndPoint, rightLineStartPoint, rightLineEndPoint)) break; if (IsLineCollisionLine2(lineStartPoint, lineEndPoint, topLineStartPoint, topLineEndPoint)) break; if (IsLineCollisionLine2(lineStartPoint, lineEndPoint, bottomLineStartPoint, bottomLineEndPoint)) break; if (IsLineCollisionLine2(lineStartPoint, lineEndPoint, leftBottomLineStartPoint, rightTopLineEndPoint)) break; if (IsLineCollisionLine2(lineStartPoint, lineEndPoint, leftTopLineStartPoint, rightBottomLineEndPoint)) break; return false; } while (false); return true; } static bool IsRectCollisionRect2(cocos2d::CCPoint rect1CenterPoint, float rect1W, float rect1H, cocos2d::CCPoint rect2CenterPoint, float rect2W, float rect2H) { cocos2d::CCPoint leftTopPoint = cocos2d::CCPoint(rect2CenterPoint.x-rect2W/2.0f, rect2CenterPoint.y+rect2H/2.0f); cocos2d::CCPoint leftBottomPoint = cocos2d::CCPoint(rect2CenterPoint.x-rect2W/2.0f, rect2CenterPoint.y-rect2H/2.0f); cocos2d::CCPoint rightTopPoint = cocos2d::CCPoint(rect2CenterPoint.x+rect2W/2.0f, rect2CenterPoint.y+rect2H/2.0f); cocos2d::CCPoint rightBottomPoint = cocos2d::CCPoint(rect2CenterPoint.x+rect2W/2.0f, rect2CenterPoint.y-rect2H/2.0f); if ( (leftTopPoint.x>(rect1CenterPoint.x-rect1W/2.0f)) && (leftTopPoint.x<(rect1CenterPoint.x+rect1W/2.0f)) && (leftTopPoint.y>(rect1CenterPoint.y-rect1H/2.0f)) && (leftTopPoint.y<(rect1CenterPoint.y+rect1H/2.0f))) return true; if ( (leftBottomPoint.x>(rect1CenterPoint.x-rect1W/2.0f)) && (leftBottomPoint.x<(rect1CenterPoint.x+rect1W/2.0f)) && (leftBottomPoint.y>(rect1CenterPoint.y-rect1H/2.0f)) && (leftBottomPoint.y<(rect1CenterPoint.y+rect1H/2.0f))) return true; if ( (rightTopPoint.x>(rect1CenterPoint.x-rect1W/2.0f)) && (rightTopPoint.x<(rect1CenterPoint.x+rect1W/2.0f)) && (rightTopPoint.y>(rect1CenterPoint.y-rect1H/2.0f)) && (rightTopPoint.y<(rect1CenterPoint.y+rect1H/2.0f))) return true; if ( (rightBottomPoint.x>(rect1CenterPoint.x-rect1W/2.0f)) && (rightBottomPoint.x<(rect1CenterPoint.x+rect1W/2.0f)) && (rightBottomPoint.y>(rect1CenterPoint.y-rect1H/2.0f)) && (rightBottomPoint.y<(rect1CenterPoint.y+rect1H/2.0f))) return true; return false; } // 矩形和矩形碰撞检测 bool IsRectCollisionRect(cocos2d::CCPoint rect1CenterPoint, float rect1W, float rect1H, cocos2d::CCPoint rect2CenterPoint, float rect2W, float rect2H) { if (IsRectCollisionRect2(rect1CenterPoint, rect1W, rect1H, rect2CenterPoint, rect2W, rect2H)) return true; if (IsRectCollisionRect2(rect2CenterPoint, rect2W, rect2H, rect1CenterPoint, rect1W, rect1H)) return true; return false; }