Pixel Perfect Collision Detection cocos2d-x v3

Hello,
I’ve tried to follow tutorial http://vietgamedev.net/blog/1215/pixel-perfect-collision-detection-using-cocos2d-x/, but it based on cocos2dx v2 version. Unfortunately, this decision works incorrect in version v3.
I found these topics:
Pixel Perfect Collision Detection
Pixel Perfect Collision Detection...version upgrade,need help
but both of them have not helped me.

Does anyone has port or other solution for Pixel Perfect Collision Detection in cocos2d-x v3 ?

Thanks in advance for any help, Alex.

1 Like

Hi, While I have never needed to do perfect pixel collision I do need to do pixel perfect touch detection (i.e. ignore touch on pixels with alpha value = 0). That tutorial is correct for v2.x.

For version 3.x you need to force a render and you need to encapsulate glReadPixel inside a CustomCommand.

Here is my current getPixelColorAt method that I am currently using un cocos2d-x v3.x

unsigned long GlobalUtils::getPixelColorAt(Node* sprite, const Vec2& point)
{

	float contentScale	= CC_CONTENT_SCALE_FACTOR();
	float width			= sprite->getContentSize().width;
	float height		= sprite->getContentSize().height;
    
    RenderTexture* pRenderer = RenderTexture::create(width, height);
	
	Point pos		= sprite->getPosition();
	Point anchor	= sprite->getAnchorPoint();
	float rangle	= sprite->getRotation();
	float iScaleX	= sprite->getScaleX();
	float iScaleY	= sprite->getScaleY();
    
	Vec2 testPoint = Vec2((point.x + width/contentScale * anchor.x) * contentScale,
                          (point.y + height/contentScale * anchor.y) * contentScale);
	
    KBRPixelReadNode* pixelReadNode = KBRPixelReadNode::create(testPoint);
    
	pRenderer->begin();
    sprite->setPosition(Vec2::ZERO);
    sprite->setAnchorPoint(Vec2::ZERO);
    sprite->setRotation(0.0f);
    sprite->setScale(1.0f, 1.0f);
    sprite->visit();
    pixelReadNode->visit(); // IMPORTANT -> THIS WILL CALL KBRPixelReadNode::draw
    pRenderer->end();
    Director::getInstance()->getRenderer()->render(); //IMPORTANT -> THIS WILL ALLOW SYNCHRONOUS BEHAVIOR
    
    if (pos.equals(Vec2::ZERO)) { //force dirty state, otherwise we would get weird draw behaviour because the model view transform would be wrong
        sprite->setPosition(Vec2(-1, -1));
    }
    sprite->setRotation(rangle);
    sprite->setPosition(pos);
    sprite->setAnchorPoint(anchor);
    sprite->setScale(iScaleX, iScaleY);

// IMPORTANT - AT THIS POINT KBRPixelReadNode::onDraw has already been executed and we can check the pixel color        

	return ((unsigned long) pixelReadNode->getPixelColor()[3]);
}

Here is the core of KBRPixelReadNode

void KBRPixelReadNode::draw(Renderer *renderer, const Mat4& transform, uint32_t flags) {
    _readPixelsCommand.init(_globalZOrder);
    _readPixelsCommand.func = CC_CALLBACK_0(KBRPixelReadNode::onDraw, this);
    renderer->addCommand(&_readPixelsCommand);
}


void KBRPixelReadNode::onDraw() {
    glReadPixels(_readPoint.x,
                 _readPoint.y,
                 1,
                 1,
                 GL_RGBA,
                 GL_UNSIGNED_BYTE,
                 &_pixelColorRead[0]);
}

So basically there are two steps you need to go through to make sure that tutorial you have linked works on cocos2d-x v3.x.

1 - Don’t just use plain glReadPixels, create a custom command and add it to the renderer.
2 - Force a Renderer::render() to check pixel color synchronously

1 Like

(oops sorry… he did not copy he did give me credit for the post)
http://blog.muditjaju.infiniteeurekas.in/?p=1

I’ll write a port of my code for Cocos2d-x 3.2 this weekend. So maybe that would help you :smile:

miguel12345, thanks! I tried something from above, but unfortunately i havn’t profound knowledges and enough experience with work of shaders and render textures.

happybirthday, it would be wonderful! Will be very grateful for you.

what about the port of this code?) it really is an indispensable thing…

Using information from this thread, I put together a solution:

1 Like

Hello,

I also posted a few months ago my own implementation:

I hope it helps :).

hi I tried to work with this solution, I have tested with a basic sprite rotated 90 degree and it seems to catch the point as it is not rotated