Hi, I just wanted to give this a bump with code tested and working for latest’s cocos version.
Note1: this post is for cocos2d-js v3. Sadly I don’t even understand why some of it works, so I take no credit for it.
Note2: I have no clue wether this method will work outside of a browser (I mean, compiling into native app, because it relies in the gl
object, which is the instance of the web rendering engine.
Note3: as said in Note2, this requires webGL, so if we are running the game in canvas renderer mode, instead of webgl renderer mode, it won’t work.
Note4: this proccess is extremely slow, so if you have several sprites overlapping and the event hast to bubble all across them finding transparent pixels you will have a nasty delay until the action is regained.
So, first we need a function that’ll take a sprite and a point and tell us if the point within that sprite is transparent:
function isSpriteTransparentInPoint(sprite, point) {
var oldPosition = sprite.getPosition();
var pixel = new Uint8Array(4);
sprite.setPosition(sprite.getParent().convertToWorldSpace(sprite.getPosition()));
var renderTexture = cc.RenderTexture.create(cc.view.getDesignResolutionSize().width, cc.view.getDesignResolutionSize().height, sprite.getTexture().getPixelFormat());
renderTexture.begin();
sprite.visit();
gl.readPixels(point.x, point.y, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, pixel);
cc.log("RGBA: " + pixel[0] + ", " + pixel[1] + ", " + pixel[2] + ", " + pixel[3]);
renderTexture.end();
sprite.setPosition(oldPosition);
//return pixel[3] < 255; //This returns true if the pixel is not completely solid
return pixel[3] === 0; //This returns true only if the pixel is completely transparent
}
And now, assuming we are modding the “Hello World” example that’s generated when you create a new cocos2d-js project, we’ll just have to add this event manager after the logo’s sprite’s been added to the layer:
cc.eventManager.addListener(cc.EventListener.create({
event: cc.EventListener.TOUCH_ALL_AT_ONCE,
onTouchesEnded: function (touches, event) {
var touch = touches[0];
if(cc.rectContainsPoint(event.getCurrentTarget().getBoundingBox(), touch.getLocation())){
if (isSpriteTransparentInPoint(event.getCurrentTarget(), touch.getLocation())) {
console.log("transparent!");
} else {
console.log("solid!");
}
}
}
}), this.sprite);
I think there’s still room for improvement, and I bet there’s got to be a way to do this with canvas render and cross-platform compilation, so I’ll post whatever I find here.
Cheers!
PS: note that, despite the thread’s original title, there’s no use of CocosBuilder here.