为啥在执行 UIPanGestureRecognizer 时此代码无法正确居中场景?

Posted

技术标签:

【中文标题】为啥在执行 UIPanGestureRecognizer 时此代码无法正确居中场景?【英文标题】:Why does this code not properly center scene when doing UIPanGestureRecognizer?为什么在执行 UIPanGestureRecognizer 时此代码无法正确居中场景? 【发布时间】:2014-08-18 23:47:50 【问题描述】:

我是使用 Xcode 的 sprite kit 为 AppStore 开发程序的初学者。我制作了一个“测试”程序,这样我就可以在将其添加到我的游戏之前尝试新事物。现在我正在摆弄一个场景——我有一个 SKNode(称为“背景”),我在其中添加了几个孩子作为 SKSpriteNodes。一个精灵节点在初始场景中可见(中心,位置 160,240),另外两个不可见:场景左侧(位置 -160,240)和场景右侧(位置 480,240)。

我希望我的游戏能够向左或向右滑动,当它向左或向右滑动时,视图将自动居中(带有动画)到三个 SKSpriteNode 之一。我使用 UIPanGestureRecognizer 移动背景节点的代码工作正常,我的自动居中视图代码工作正常(背景位置设置为 0,0 或 -320,0 或 +320,0),但有时它有一个奇怪的偏移并且不会完全居中(例如,当我向右或向左平移时,背景位置将为 7,0 或 -34,0)。我做错了什么?

P.S:我正在为 SKTMoveEffect 使用 RayWenderlich 的“ios 游戏”中的代码。我还想指出,如果我使函数 f(t)=t,没有问题(至少在我的几次测试中),但 f(t)=t^2 或其他任何东西似乎都有问题;如果它有助于查看此代码,我也可以发布它

@implementation LTMyScene

    SKNode *background;
    SKSpriteNode *spaceship1, *spaceship2;

-(id)initWithSize:(CGSize)size     
    if (self = [super initWithSize:size]) 
        /* Setup your scene here */
        background=[SKNode node];
        [self addChild:background];
        self.backgroundColor = [SKColor colorWithRed:0.15 green:0.15 blue:0.3 alpha:1.0];

        SKLabelNode *myLabel = [SKLabelNode labelNodeWithFontNamed:@"Chalkduster"];
        myLabel.text = @"Hello, World!";
        myLabel.fontSize = 30;
        myLabel.position = CGPointMake(CGRectGetMidX(self.frame),
                                       CGRectGetMidY(self.frame));

        [background addChild:myLabel];

        spaceship1=[SKSpriteNode spriteNodeWithImageNamed:@"Spaceship.png"];
        spaceship1.position=CGPointMake(-self.size.width/2, self.size.height/2);
        spaceship1.anchorPoint=CGPointMake(0.5, 0.5);
        [background addChild:spaceship1];

        spaceship2=[SKSpriteNode spriteNodeWithImageNamed:@"Spaceship.png"];
        spaceship2.position=CGPointMake(self.size.width*3/2, self.size.height/2);
        spaceship2.anchorPoint=CGPointMake(0.5, 0.5);
        [background addChild:spaceship2];
    
    return self;


- (void)didMoveToView:(SKView *)view


    UIPanGestureRecognizer *swipe = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(dragPlayer:)];
    [[self view] addGestureRecognizer:swipe];


-(void)dragPlayer: (UIPanGestureRecognizer *)gesture 
    [[[self view] layer] removeAllAnimations];
    CGPoint trans = [gesture translationInView:self.view];
    SKAction *moveAction =  [SKAction moveByX:trans.x y:0  duration:0];
    [background runAction:moveAction];
    [gesture setTranslation:CGPointMake(0, 0) inView:self.view];


    if([gesture state] == UIGestureRecognizerStateEnded) 
        CGFloat finalX=0;
        if (abs(background.position.x)<self.size.width/2) 
            finalX=0;
         else if (abs(background.position.x)<self.size.width*3/2) 
            finalX=self.size.width*background.position.x/abs(background.position.x);
        
        NSLog(@"%f",finalX);

        SKTMoveEffect *upEffect =
        [SKTMoveEffect effectWithNode:background duration:0.5
                        startPosition:background.position
                          endPosition:CGPointMake(finalX, 0)];

        upEffect.timingFunction = ^(float t) 
//            return powf(2.0f, -3.0f * t) * fabsf(cosf(t * M_PI * 1.0f)) //has bounce
//            return (-1.0f*t*t+1) //no bounce ... for parabola this is only solution with (1,0) and (0,1) as intercepts and vertex at (1,0)
            return (t*t)
            ;;

        SKAction *upAction = [SKAction actionWithEffect:upEffect];
        [background runAction:upAction];
    

-(void)update:(CFTimeInterval)currentTime 
    /* Called before each frame is rendered */
    NSLog(@"%f,%f",background.position.x,background.position.y);


@end

【问题讨论】:

【参考方案1】:

您必须记住,您正在移动较大的背景节点,并将其他节点作为其子节点。请记住,您需要以特定节点为中心的代码是:

_worldNode.position = CGPointMake(-(myNode.position.x-(self.size.width/2)), -(myNode.position.y-(self.size.height/2)));

以上假设您的主背景“画布”称为_worldNode,并且您的目标节点是_worldNode 的子节点

【讨论】:

以上是关于为啥在执行 UIPanGestureRecognizer 时此代码无法正确居中场景?的主要内容,如果未能解决你的问题,请参考以下文章

快速检测两个 UIView 的碰撞

为啥火花中的一些音符工作得非常慢?为啥在同一情况下多次执行有不同的执行时间?

在执行语义分割任务时我应该减去图像均值吗?为啥或者为啥不?

为啥我的程序在实际应该执行之前执行?

为啥 NSManagedObjectContext 队列在主线程上执行?

为啥我在执行 doInBackground() 时出错