cocos2d-x中的碰撞检测

今天在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,如下图所示
cocos2d-x中的碰撞检测

以圆心为原点新建一个坐标系,碰撞检测分两种情况:
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与圆未碰撞

如有问题,还请指正~



cocos2d-x中的碰撞检测

上一篇:Cocos2d-x 创建精灵的五种方法


下一篇:I,P,B帧和PTS,DTS的关系<转>