物理エンジンを使用しない場合、コリジョン判定(当たり判定)はスプライトの矩形で行うことが多いと思います。これを透過画像の透過部分を当たり判定に含めない方法を紹介します。
HelloWorld::areSpritesColliding メソッドでは、指定した2つのスプライトが透過部分を除いて重なっていれば、true を返します。スプライト同士の当たり判定に使用できます。
HelloWorld::collideAtPoint メソッドでは、指定したスプライトと指定した座標が透過していないピクセルなら true を返します。タップした場所に画像がある(透過されていない)か判定する場合に使用できます。
CCLayer クラスで実装していますが、少し改良して CCSpirte を拡張したクラスを作成して、使用するとよいかもしれません。
HelloWorld.cpp
bool HelloWorld::areSpritesColliding(cocos2d::CCSprite *spr1, cocos2d::CCSprite *spr2, bool pp) {
bool isColliding = false;
CCRect intersection;
CCRect r1 = spr1->boundingBox();
CCRect r2 = spr2->boundingBox();
// Look for simple bounding box collision
if (r1.intersectsRect(r2)) {
// If we're not checking for pixel perfect collisions, return true
if (!pp) {
return true;
}
CCLOG("Bounding Box Collision");
float tempX;
float tempY;
float tempWidth;
float tempHeight;
if (r1.getMaxX() > r2.getMinX()) {
tempX = r2.getMinX();
tempWidth = r1.getMaxX() - r2.getMinX();
} else {
tempX = r1.getMinX();
tempWidth = r2.getMaxX() - r1.getMinX();
}
if (r1.getMinY() < r2.getMaxY()) {
tempY = r1.getMinY();
tempHeight = r2.getMaxY() - r1.getMinY();
} else {
tempY = r2.getMinY();
tempHeight = r1.getMaxY() - r2.getMinY();
}
intersection = CCRectMake(tempX * CC_CONTENT_SCALE_FACTOR(), tempY * CC_CONTENT_SCALE_FACTOR(), tempWidth * CC_CONTENT_SCALE_FACTOR(), tempHeight * CC_CONTENT_SCALE_FACTOR());
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;
if (numPixels<=0) return false;
// Draw into the RenderTexture
CCSize size = CCDirector::sharedDirector()->getWinSize();
CCRenderTexture *rt = CCRenderTexture::create(size.width, size.height, kCCTexture2DPixelFormat_RGBA8888);
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<numPixels; i+=step) {
ccColor4B color = buffer[i];
CCLOG("Pixel color: %d, %d, %d", color.r, color.g, color.b);
if (color.r > 0 && color.g > 0) {
isColliding = true;
CCLOG("Colliding");
break;
}
}
// Free buffer memory
free(buffer);
}
return isColliding;
}
bool HelloWorld::collideAtPoint(cocos2d::CCSprite* pSprite, cocos2d::CCPoint point) {
bool bCollision = false;
int searchWidth = 1;
int searchHeight = 1;
unsigned int numPixels = searchWidth * searchHeight;
CCSize size = CCDirector::sharedDirector()->getWinSize();
CCRenderTexture *rt = CCRenderTexture::create(size.width, size.height, kCCTexture2DPixelFormat_RGBA8888);
rt->beginWithClear(0, 0, 0, 0);
// Render both sprites: first one in RED and second one in GREEN
glColorMask(1, 0, 0, 1);
pSprite->visit();
glColorMask(1, 1, 1, 1);
// Get color values of intersection area
ccColor4B *buffer = (ccColor4B *)malloc( sizeof(ccColor4B) * numPixels );
glReadPixels(point.x, point.y, searchWidth, searchHeight, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
unsigned int step = 1;
for(unsigned int i=0; i<numPixels; i+=step) {
ccColor4B color = buffer[i];
//CCLog("Pixel color: %d, %d, %d", color.r, color.g, color.b);
if (color.r > 0) {
bCollision = true;
CCLOG("Colliding");
break;
}
}
rt->end();
return bCollision;
}