【问题标题】:Sprite-Kit Pinch to Zoom Problems UIPinchGestureRecognizerSprite-Kit 捏缩放问题 UIPinchGestureRecognizer
【发布时间】:2014-04-08 11:27:00
【问题描述】:

我已经在这段代码上工作了很长一段时间,但感觉就像前进了一步,后退了两步。我希望有人可以帮助我。

我正在使用 Sprite Kit,所以我有一个管理渲染、UI 和触摸控件的场景文件。我有一个 SKNode,它像这样用作相机:

_world = [[SKNode alloc] init];
[_world setName:@"world"];
[self addChild:_world];

我正在使用 UIGestureRecognizer,所以我添加了我需要的那些:

_panRecognizer = [[UIPanGestureRecognizer alloc]initWithTarget:self action:@selector(handlePanFrom:)];
[[self view] addGestureRecognizer:_panRecognizer];
_pinchRecognizer = [[UIPinchGestureRecognizer alloc]initWithTarget:self action:@selector(handlePinch:)];
[[self view] addGestureRecognizer:_pinchRecognizer];

平移工作正常,但不是很好。捏是真正的问题。捏合的想法是在屏幕中心抓取一个点,将该点转换为世界节点,然后在放大的同时移动到它。捏合的方法如下:

-(void) handlePinch:(UIPinchGestureRecognizer *)sender {
if (sender.state == UIGestureRecognizerStateBegan) {
    _tempScale = [sender scale];
}
if (sender.state == UIGestureRecognizerStateChanged) {
    if([sender scale] > _tempScale) {
        if (_world.xScale < 6) {
            //_world.xScale += 0.05;
            //_world.yScale += 0.05;
            //[_world setScale:[sender scale]];
            [_world setScale:_world.xScale += 0.05];

            CGPoint screenCenter = CGPointMake(_initialScreenSize.width/2, _initialScreenSize.height/2);
            CGPoint newWorldPoint = [self convertTouchPointToWorld:screenCenter];

            //crazy method why does this work
            CGPoint alteredWorldCenter = CGPointMake(((newWorldPoint.x*_world.xScale)*-1), (newWorldPoint.y*_world.yScale)*-1);

            //why does the duration have to be exactly 0.3 to work
            SKAction *moveToCenter = [SKAction moveTo:alteredWorldCenter duration:0.3];
            [_world runAction:moveToCenter];
        }
    } else if ([sender scale] < _tempScale) {
        if (_world.xScale > 0.5 && _world.xScale > 0.3){
            //_world.xScale -= 0.05;
            //_world.yScale -= 0.05;
            //[_world setScale:[sender scale]];
             [_world setScale:_world.xScale -= 0.05];

            CGPoint screenCenter = CGPointMake(_initialScreenSize.width/2, _initialScreenSize.height/2);
            CGPoint newWorldPoint = [self convertTouchPointToWorld:screenCenter];

            //crazy method why does this work
            CGPoint alteredWorldCenter = CGPointMake(((newWorldPoint.x*_world.xScale - _initialScreenSize.width)*-1), (newWorldPoint.y*_world.yScale - _initialScreenSize.height)*-1);

            SKAction *moveToCenter = [SKAction moveTo:alteredWorldCenter duration:0.3];
            [_world runAction:moveToCenter];
        }
    }
}
if (sender.state == UIGestureRecognizerStateEnded) {
    [_world removeAllActions];
}
}

我已经尝试了很多次迭代,但是这个确切的代码是让我最接近世界上某个点的原因。不过也有一些问题。当你离中心越来越远时,它就不能正常工作了,因为它几乎仍然试图放大世界的中心。将中心点转换为世界节点后,我仍然需要再次对其进行操作以使其正确居中(我描述为疯狂的公式)。放大和缩小工作必须有所不同。移动动作的持续时间必须设置为 0.3,否则它几乎不起作用。更高或更低,它不会放大中心点。如果我尝试将缩放幅度增加不止一点,它会疯狂地快速移动。如果我在捏合结束时不结束动作,屏幕就会抖动。我不明白为什么这完全有效(它在延迟结束和屏幕抖动之前平滑地放大到中心点)而且我不确定我做错了什么。非常感谢任何帮助!

【问题讨论】:

    标签: ios objective-c zooming sprite-kit pinch


    【解决方案1】:

    看看我对一个非常相似的问题的回答。

    https://stackoverflow.com/a/21947549/3148272

    我发布的代码将缩放“锚定”在捏合手势的位置而不是屏幕的中心,但由于我尝试了两种方式,因此很容易更改。

    根据下面 cmets 的要求,我还将我的平移代码添加到此答案中。

    平移代码...

    // instance variables of MyScene.
    SKNode *_mySkNode;
    UIPanGestureRecognizer *_panGestureRecognizer;
    
    - (void)didMoveToView:(SKView *)view
    {
        _panGestureRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePanFrom:)];
        [[self view] addGestureRecognizer:_panGestureRecognizer];
    }
    
    - (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);
    
            _mySkNode.position = CGPointSubtract(_mySkNode.position, translation);
    
            [recognizer setTranslation:CGPointZero inView:recognizer.view];
    
        } else if (recognizer.state == UIGestureRecognizerStateEnded) {
    
            // No code needed for panning.
        }
    }
    

    以下是上面使用的两个辅助函数。它们来自 Ray Wenderlich 关于 Sprite Kit 的书。

    SKT_INLINE CGPoint CGPointAdd(CGPoint point1, CGPoint point2) {
        return CGPointMake(point1.x + point2.x, point1.y + point2.y);
    }
    
    SKT_INLINE CGPoint CGPointSubtract(CGPoint point1, CGPoint point2) {
        return CGPointMake(point1.x - point2.x, point1.y - point2.y);
    }
    

    【讨论】:

    • 您在该页面上的回答确实非常有效。我不知道该怎么感谢你才足够!你会以什么方式发布你的平移代码?我很想看看你的方法。
    • 当然。平移实际上要容易得多。我刚刚在上面的答案中添加了平移代码。
    • 谢谢,帮了我很多忙! :D
    猜你喜欢
    • 2011-11-18
    • 2015-12-16
    • 1970-01-01
    • 2011-02-11
    • 2012-11-30
    • 2012-06-25
    • 2023-03-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多