今天在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与圆未碰撞
如有问题,还请指正~