Search code examples
iossprite-kituipangesturerecognizeruipinchgesturerecognizer

Limit Pan Gesture with Pinch Gesture


I'm creating a game in Spritekit and am using the Pan Gesture with the Pinch Gesture in order to view a map. Currently I am limiting the zoom of the Pinch Gesture to 2.0 scale. I'm trying to limit the Pan Gesture to the bounds of the screen even when zoomed. The map is larger than the screen and I only want the user to be able to pan around until the outer edge of the map hits the outer edge of the screen, even when zoomed. Here is my amateur way of trying to handle the situation:

-(void) handlePanFrom:(UIPanGestureRecognizer*)recognizer {
    if (recognizer.state == UIGestureRecognizerStateBegan) {
        [recognizer setTranslation:CGPointZero inView:recognizer.view];
    } else if (recognizer.state == UIGestureRecognizerStateChanged) {
        CGPoint translation = [recognizer translationInView:recognizer.view];
        translation = CGPointMake(-translation.x, translation.y);
        CGPoint desiredPos = CGPointSubtract(_mapNode.position, translation);
        NSLog(@"Moving map to x: %f y: %f", desiredPos.x, desiredPos.y);
        NSLog(@"Map node position x: %f y: %f", _mapNode.position.x, _mapNode.position.y);
        NSLog(@"Map scale is %f", mapScale);
        NSLog(@"Map size is x: %f y: %f", _mapNode.map.frame.size.width, _mapNode.map.frame.size.height);

        if (desiredPos.y <= (mapScale * 300) && desiredPos.y >= ((1/mapScale) * 200)) {
            _mapNode.position = CGPointMake(_mapNode.position.x, desiredPos.y);
            [recognizer setTranslation:CGPointZero inView:recognizer.view];
        }

        if (desiredPos.x <= (mapScale * 250) && desiredPos.x >= ((1/mapScale) * 77)) {
            _mapNode.position = CGPointMake(desiredPos.x, _mapNode.position.y);
            [recognizer setTranslation:CGPointZero inView:recognizer.view];
        }
    } else if (recognizer.state == UIGestureRecognizerStateEnded) {

    }
}

I set a scale iVar when zooming to get the scale of the node. I should be able to use the sizes of the nodes (_mapNode.map is an SKSpriteNode) and the screen size to get the panning I want.

I thought I could do scale*xMax and (1/scale)*xMin (also with y position) but that doesn't seem to work. I would love to not have hard numbers in there (300, 200, etc) and use the sizing of the nodes/screen/etc to limit the panning. Any help is appreciated! Thanks!


Solution

  • Okay this is what I did for future reference for people.

    I first created two iVars: one for the initial x position of the node and one for the initial y position. I then calculated a 'movable distance' by taking: sizeOfNode * 0.5 * scale and subtracting screenSize * 0.5. As long as desiredLocation <= (initialPos + movableDistance) and desiredLocation >= (initialPos - moveableDistance) then you could change the position of the node. You can do this for both x and y.