I'm using Cocos2d for developing a game. I need to be able to pan and zoom when necessary, so for this reason I've added CCLayerPanZoom extension to my project. Recently I've noticed a problem with zoomed layers. The thing is if I touch on a zoom-panable layer before doing zooming or panning I get correct x,y coordinates. But if I zoom the layer, the touched location coordinates are different than the earlier ones. Here's how I get the touch location:

-(void)ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
    UITouch *touch=[touches anyObject];
    CGPoint touchedLocation=[touch locationInView:touch.view];
    touchedLocation=[[CCDirector sharedDirector] convertToGL:startPoint];

You might ask how I determine whether the two points are different before and after zooming. I have a sprite located on a predetermined point in the view. When I touch the sprite I log the position of both the sprite and the touchedLocation. Before zooming these points are almost the same, only a few units of difference in x and y. But after zooming they're totally different points and I guess this difference is directly proportional with the zoom scale. I don't want to ask how to have the touched location the same before and after zooming, I rather want to ask what I should do in this case.

int Width = 2500;

int Height = 1500;

CCLayerPanZoom *Zooming = [[CCLayerPanZoom alloc] init];

self.Zooming.mode = kCCLayerPanZoomModeSheet;

self.Zooming.panBoundsRect = CGRectMake( 0, 0, mapWidth, mapHeight );

// zooming level

self.Zooming.minScale = 1.0f;

self.Zooming.maxScale = 8.0f;

self.Zooming.rubberEffectRatio = 0.0f;

// center in the view

self.Zooming.position = ccp( 512, 384 );

// the position just seems to make it all more or less weird, this is for testing

View.position = ccp( mapWidth * 0.5f, mapHeight * 0.5f );

[self.Zooming addChild:View];

[self addChild:self.Zooming];

OK, I finally got where my mistake was. I forgot the fact that when I add a sprite on a layer and later refer to its position, it always shows the same point. So for instance, if I add a sprite and set its position to 100,100 and then pan or zoom the layer and finally get the position of the sprite I'll still get 100, 100, even if the sprite is not inside the bounds of the screen for the moment. So when I touch the sprite after the layer is panned or zoomed I touch to a different position, not 100,100. That was what made me confused. To handle this issue I just subtracted the x,y of the layer's position from those of the touched location. This way I was able get the two points - the sprite's position and the touched location- to be the same. Note: The anchor point of the layer is ccp(0,0);


You can refer to this code block:

- (void) layerPanZoom: (CCLayerPanZoom *) sender
       clickedAtPoint: (CGPoint) point
             tapCount: (NSUInteger) tapCount
    NSLog(@"CCLayerPanZoomTestLayer#layerPanZoom: %@ clickedAtPoint: { %f, %f }", sender, point.x, point.y);

    if (tapCount == 2) {
        // Toggle zooming all the way in and all the way out.

        float midScale = (sender.minScale + sender.maxScale) / 2.0;
        float newScale = (sender.scale <= midScale) ? sender.maxScale : sender.minScale;

        // Zoom towards the tap point.  Note that scaling is performed "around" the anchor point.
        // Thus, we need to account for how far the layer should be translated after its scaling
        // change is performed.

        CGPoint anchorPointNodeSpace = ccp(sender.anchorPoint.x * sender.contentSize.width,
                                           sender.anchorPoint.y * sender.contentSize.height);       

        CGFloat deltaScale = newScale - sender.scale;

        CGPoint deltaPos = ccpMult(ccpSub(point, anchorPointNodeSpace), deltaScale);

        // Scale and translate in parallel.  We negate the direction since to zoom to the point
        // we want to move the layer in the opposite direction.

        [sender runAction:[CCSpawn actions:
                           [CCScaleTo actionWithDuration:0.4 scale:newScale],
                           [CCMoveBy actionWithDuration:0.4 position:ccpNeg(deltaPos)],

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.