在 iOS 7 中以透明背景在 Cocos2D 中放慢速度



我已经在 Cocos2D 中开发了大约 3 年的游戏,它利用透明背景来显示 UIView。这样做的原因是,当 Cocos2D 执行场景过渡时,视差背景仍然运行。

我有一个新问题,当我更新到 iOS 7 时开始。 减速发生在以下情况的组合中:

-仅当视差背景的帧位置发生变化时。

-如果我消灭一个敌人,发射出小精灵和粒子效果。

所以这是这两件事的结合,它只是偶尔发生。 当速度变慢时,帧速率的调试值不会下降。如果我加载一个新场景,它会恢复正常。有时当我消灭另一个敌人时,减速也会消失。

我的视差 UIView 中有代码,几乎可以运行游戏中的每一帧。 我将问题总结为一行:

-(void)updateImagePosWithPos:(CGPoint)pos{ // in game
    // create vel based on last currentPos minus new pos
    CGPoint vel = CGPointMake(currentPos.x-pos.x, currentPos.y-pos.y);
    // init variables tmpVel and tempTotalImages
    CGPoint tmpVel = CGPointZero;
    int tmpTotalImages = 0;
    // create indexLayerArr
    NSMutableArray *indexLayerArr = [NSMutableArray array];
    // for every parallax layer, add the number of images horizontally minus 1 to indexLayerArr
    for (int j=0; j<totalLayers; ++j){
        [indexLayerArr addObject:[NSNumber numberWithInt:[[totalImagesArr objectAtIndex:j] intValue]-1]];
    }
    int i = 0;

    for (UIImageView *imageView in self.subviews) {
        CGRect tmpRect = CGRectZero;
        NSMutableArray *tmpRectArr = [rectContainer objectAtIndex:imageView.tag];
        float speed = 0.00;

        tmpTotalImages = [[totalImagesArr objectAtIndex:imageView.tag] intValue];
        speed = [[speedArr objectAtIndex:imageView.tag] floatValue];
        tmpVel = CGPointMake(vel.x*speed, vel.y*speed);
        i = [[indexLayerArr objectAtIndex:imageView.tag] intValue];
        tmpRect = [[tmpRectArr objectAtIndex:i] CGRectValue];

        if(tmpRect.origin.x - tmpVel.x > wins.width){
            tmpRect.origin.x -= (tmpTotalImages)*tmpRect.size.width;
        }
        else if(tmpRect.origin.x - tmpVel.x < -tmpRect.size.width){
            tmpRect.origin.x += (tmpTotalImages)*tmpRect.size.width;
        }
        tmpRect.origin.x -= tmpVel.x;
        tmpRect.origin.y += tmpVel.y;
        [tmpRectArr replaceObjectAtIndex:i withObject:[NSValue valueWithCGRect:tmpRect]];

        imageView.frame = [[tmpRectArr objectAtIndex:i] CGRectValue]; // <-- slow down cause

        i--;
        [indexLayerArr replaceObjectAtIndex:imageView.tag withObject:[NSNumber numberWithInt:i]];

    }
    currentPos = CGPointMake(pos.x, pos.y);
}

请参阅注释行图像视图.帧 = [[tmpRectArr objectAtIndex:i] CGRectValue];

因此,如果我注释掉那行,问题将永远不会发生。 如果我保留该行并且不更改 tempRect 的值,问题也不会发生。

看起来iOS 7在更改UIImageView的帧位置时存在问题,但只是有时。 只是想知道我可以使用哪些其他替代方案?还是我在iOS 7中做错了什么?

不是您问题的解决方案,而是解决方法。我将从可能需要最多代码更改的那个开始。

  1. 您实际上不必拥有UIView即可保持背景与过渡。相反,如果您完全在 cocos2d 中实现背景(作为场景的一部分),则无需替换场景,而是将图层移入和移出,则可以达到相同的效果。在大多数情况下,场景过渡使用同样适用于节点的相同操作。

  2. 使用 cocos2d 节点实现后台,并让一个父节点充当后台节点的容器(即"层")。您可以对该节点执行以下两项操作之一:

    a. 编辑 CCDirectorIOS 的代码并添加对后台节点的引用。在 drawScene 方法中的所有其他节点之前更新节点,方法是在后台节点上调用 visit [_runningScene visit] 之前。

    二.过渡到新场景时,请从当前场景中移除背景节点并将其添加到新场景中,或者创建具有所有相同设置的背景副本并将其添加到新场景中。确保副本以与原始副本完全相同的状态开始。尽管由于其动画的性质(即移动/翻转/缩放),这不适用于大多数过渡。

  3. 如果您需要背景在过渡运行时进行动画处理,有一个简单的技巧。在具有全局生存期(即应用程序委托)的非 CCNode 对象上计划更新。然后手动将更新发送到应在转换期间(并且仅在转换期间)继续更新其状态的所有节点。

您可以在非节点对象上注册更新,如下所示:

[_director.scheduler scheduleUpdateForTarget:self priority:0 paused:NO];

即使在场景转换期间也会调用此更新方法。或者,还应该可以通过更改节点的paused状态来继续更新节点,从而恢复调度程序和操作,方法是重写 paused 属性或在发生转换时显式取消暂停特定节点。

最新更新