今天在csdn看到一篇文章,写矩形与圆形的碰撞检测,借鉴了作者的检测思路,我把它用到了cocos2d-x中。
原文章的地址:点击打开链接
在cocos2d-x中已经提供了矩形与矩形的碰撞检测以及点与矩形的碰撞检测,如下:
检测矩形与矩形碰撞的函数:
bool intersectsRect(const CCRect &rect)
使用方法:
rect1.intersectsRect(rect2);
检测点与矩形碰撞的函数:
bool containsPoint(const CCPoint &point)
使用方法:
rect.containsPoint(point);
下面重点说矩形与圆形的碰撞检测:
PS:先说一下cocos2d-x中的矩形Rect,Rect的构造有四个参数,x, y, width, height,如下图所示
以圆心为原点新建一个坐标系,碰撞检测分两种情况:
1.整个矩形位于同一个象限中
怎么判断是否只在一个象限呢?看一对对角顶点是否位于同一象限就可以了,判断这两个顶点的x,y坐标是否同号即可。
检测四个顶点中若有至少一个顶点位于圆内,矩形和圆形就碰撞了;否则没有。
2.矩形位于两个或四个象限中(不会出现三个的情况)
这时候可以检测矩形与圆的外切正方形时候碰撞,它们的检测结果和矩形与圆的检测结果相同。
实现如下,会有必要的注释:
// // CGCircle.h // HelloCpp // // Created by Mike on 14-1-16. // // #ifndef __HelloCpp__CGCircle__ #define __HelloCpp__CGCircle__ #include <iostream> #include "cocos2d.h" using namespace std; using namespace cocos2d; class CGCircle { private: //float _radius; //半径 //Point _position; //圆心 public: CC_SYNTHESIZE(float, _radius, Radius); CC_SYNTHESIZE(Point, _position, Position); CGCircle(float radius, Point position): _radius(radius), _position(position){}; bool isContainRect(Rect rect); }; #endif /* defined(__HelloCpp__CGCircle__) */
// // CGCircle.cpp // HelloCpp // // Created by Mike on 14-1-16. // // #include "CGCircle.h" bool CGCircle::isContainRect(Rect rect) { bool _isContian = false; Point orign = _position; //圆心,新建坐标系的原点 //圆的外切正方形 Rect(x, y, width, heigth) x,y是原点,左下顶点 Rect square = Rect::Rect(_position.x - _radius, _position.y - _radius, 2 * _radius, 2 * _radius); do { Point rectVertex0 = rect.origin; //左下 Point rectVertex1 = rect.origin + Point(rect.size.width, 0); //右下 Point rectVertex2 = rect.origin + Point(rect.size.width, rect.size.height); //右上 Point rectVertex3 = rect.origin + Point(0, rect.size.height); //左上 Point pos[] = {rectVertex0, rectVertex1, rectVertex2, rectVertex3}; if ((pos[1].x - orign.x) * (pos[3].x - orign.x) > 0 && (pos[1].y - orign.y) * (pos[3].y - orign.y) > 0) { //右下顶点和左上顶点在同一象限,说明整个矩形位于一个象限内 若各顶点至少有一个在圆内则相交 for (int i = 0; i < 4; i++) { //判断矩形四个顶点是否至少有一个位于圆内 if (((pos[i].x - orign.x) * (pos[i].x - orign.x) + (pos[i].y - orign.y) * (pos[i].y - orign.y)) <= _radius * _radius) { goto next; } } } if (square.intersectsRect(rect)) { goto next; } for (int i = 0; i < 4; i++) { if (pos[i] == orign) { goto next; } } break; next: _isContian = true; } while (0); return _isContian; }
Size visibleSize = Director::getInstance()->getVisibleSize(); auto circleS = Sprite::create("circle.png"); circleS->setPosition(Point(visibleSize.width/2, visibleSize.height/2)); this->addChild(circleS, 0); auto rectS = Sprite::create("rect.png"); rectS->setPosition(Point(circleS->getPositionX() - 100, circleS->getPositionY())); this->addChild(rectS, 0); CGCircle circle0 = CGCircle(circleS->getContentSize().width/2, circleS->getPosition()); Rect rect0 = Rect(rectS->getPositionX() - rectS->getContentSize().width/2, rectS->getPositionY() - rectS->getContentSize().height/2, rectS->getContentSize().width, rectS->getContentSize().height); if (circle0.isContainRect(rect0)) { CCLOG("circleS与rectS碰撞了"); } else CCLOG("circleS与rectS未碰撞"); float radius = 30.0; Point position = Point(300, 300); CGCircle circle = CGCircle(radius, position); Rect rect1 = Rect(280, 290, 10, 30); if (circle.isContainRect(rect1)) { CCLOG("矩形1与圆碰撞了"); } Rect rect2 = Rect(210, 290, 10, 30); if (! circle.isContainRect(rect2)) { CCLOG("矩形2与圆未碰撞"); }测试输出:
cocos2d: circleS与rectS未碰撞 cocos2d: 矩形1与圆碰撞了 cocos2d: 矩形2与圆未碰撞
如有问题,还请指正~