Search code examples
cocos2d-iphonekobold2d

CCSprite children coordinates transform fails when using CCLayerPanZoom and CCRenderTexture?


Thanks for reading.

I'm working on a setup in Cocos2D 1.x where I have a huge CCLayerPanZoom in a scene with free panning and zooming. Every frame, I have to additionally draw a CCRenderTexture on top to create "darkness" (I'm cutting out the light). That works well.

Now I've added single sprites to the surface, and they are managed by Box2D. That works as well. I can translate to the RenderTexture where the light sources ought to be, and they render fine.

And then I wanted to add a HUD layer on top, by adding a CCLayer to the scene. That layer needs to contain several sprites stacked on top of each other, as user interface elements.

Only, all of these elements fail to draw where I need them to be: Exactly in the center of screen. The Sprites added onto the HUD layer are all off, and I have iterated through pretty much every variation "convertToWorldSpace", "convertToNodeSpace", etc.

It is as if the constant scaling by the CCPanZoomLayer in the background throws off anchor points in the layer above each frame, and resetting them doesn't help. They all seem to default into one of the corners of the node bounding box they are attached to, as if their transform is blocked or set to zero when it comes to the drawing.

Has anyone run into this problem? Is this a known issue when using CCLayerPanZoom and drawing a custom CCRenderTexture on top each frame?


Solution

  • Ha! I found the culprit! There's a bug in Cocos2D' way of using Zwoptex data. (I'm using Cocos2D v 1.0.1).

    It seems that when loading in Zwoptex v3 data, sprite frames' trim offset data is ignored when the actual sprite frame anchor point is computed. The effect is that no anchor point on a sprite with trim offset in its definition (eg in the plist) has its anchor point correctly set. Really strange... I wonder whether this has occurred to anybody else? It's a glaring issue.

    Here's how to reproduce: Create any data for a sprite frame in zwoptex v3 format (the one that uses the trim data). Make sure you actually have a trimmed sprite, i.e. offset must be larger than zero, and image size must be larger than source. Load in sprite, and try to position it at center of screen. You'll see it's off. Here's how to compute your anchor point correctly:

            CCSprite *floor = [CCSprite spriteWithSpriteFrameName:@"Menu_OmeFloor.png"]; //create a sprite
            CCSpriteFrame *frame=[[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:@"Menu_OmeFloor.png"]; //get its frame to access frame data
            [floor setTextureRectInPixels:frame.rect rotated:frame.rotated untrimmedSize:frame.originalSizeInPixels]; //re-set its texture rect
            //Ensure that the coordinates are right: Texture frame offset is not counted in when determining normal anchor point:
            xa = 0.5 + (frame.offsetInPixels.x / frame.originalSizeInPixels.width);
            ya = 0.5 + (frame.offsetInPixels.y / frame.originalSizeInPixels.height);
            [floor setAnchorPoint:ccp(xa,ya)];
            floor.position=(where you need it);
    

    Replace the 0.5 in the xa/ya formula with your required anchor point values.