3
\$\begingroup\$

I am trying to port the pixel perfect collision detection in Cocos2d-x the original version was made for Cocos2D and can be found here: http://www.cocos2d-iphone.org/forums/topic/pixel-perfect-collision-detection-using-color-blending/

Here is my code for the Cocos2d-x version

bool CollisionDetection::areTheSpritesColliding(cocos2d::CCSprite *spr1, cocos2d::CCSprite *spr2, bool pp, CCRenderTexture* _rt) {
    bool isColliding = false;
    CCRect intersection;
    CCRect r1 = spr1->boundingBox();
    CCRect r2 = spr2->boundingBox();
    intersection = CCRectMake(fmax(r1.getMinX(),r2.getMinX()), fmax( r1.getMinY(), r2.getMinY()) ,0,0);
    intersection.size.width = fmin(r1.getMaxX(), r2.getMaxX() - intersection.getMinX());
    intersection.size.height = fmin(r1.getMaxY(), r2.getMaxY() - intersection.getMinY());

    // Look for simple bounding box collision
    if ( (intersection.size.width>0) && (intersection.size.height>0) ) {
        // If we're not checking for pixel perfect collisions, return true
        if (!pp) {
            return true;
        }

        unsigned int x = intersection.origin.x;
        unsigned int y = intersection.origin.y;
        unsigned int w = intersection.size.width;
        unsigned int h = intersection.size.height;
        unsigned int numPixels = w * h;
        //CCLog("Intersection X and Y %d, %d", x, y);
        //CCLog("Number of pixels %d", numPixels);

        // Draw into the RenderTexture
        _rt->beginWithClear( 0, 0, 0, 0);

        // Render both sprites: first one in RED and second one in GREEN
        glColorMask(1, 0, 0, 1);
        spr1->visit();
        glColorMask(0, 1, 0, 1);
        spr2->visit();
        glColorMask(1, 1, 1, 1);

        // Get color values of intersection area
        ccColor4B *buffer = (ccColor4B *)malloc( sizeof(ccColor4B) * numPixels );
        glReadPixels(x, y, w, h, GL_RGBA, GL_UNSIGNED_BYTE, buffer);

        _rt->end();

        // Read buffer
        unsigned int step = 1;
        for(unsigned int i=0; i 0 && color.g > 0) {
                isColliding = true;
                break;
            }
        }

        // Free buffer memory
        free(buffer);
    }


    return isColliding;
}

My code is working perfectly if I send the "pp" parameter as false. That is if I do only a bounding box collision but I am not able to get it working correctly for the case when I need Pixel Perfect collision. I think the opengl masking code is not working as I intended.

Here is the code for "_rt"

_rt = CCRenderTexture::create(visibleSize.width, visibleSize.height);
_rt->setPosition(ccp(origin.x + visibleSize.width * 0.5f, origin.y + visibleSize.height * 0.5f));
this->addChild(_rt, 1000000);
_rt->setVisible(true); //For testing

I think I am making a mistake with the implementation of this CCRenderTexture

Can anyone guide me with what I am doing wrong ?

Thank you for your time :)

\$\endgroup\$
  • 1
    \$\begingroup\$ I hate seeing the phrase "Pixel Perfect." Who coined that... \$\endgroup\$ – Tonithy Sep 28 '13 at 3:24
1
\$\begingroup\$

Solved the problem finally.

Had to use custom openGL shaders for coloring one of the objects completely RED and the other completely BLUE and then looping through all the pixel data collected using glReadPixels to find if a pixel has both RED and BLUE colors.

In depth information and source code can be found in my blog post - http://blog.muditjaju.infiniteeurekas.in/?p=1

\$\endgroup\$
  • 1
    \$\begingroup\$ glReadPixels can be slow and stall the graphics pipeline on some hardware/drivers. You might want to consider comparing the speed of the GL version with doing it all CPU-side (especially if you build, say, octrees or KD-trees for the sprites instead of comparing pixel-by-pixel). \$\endgroup\$ – Sean Middleditch Sep 28 '13 at 1:13

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.