多次重绘GameHUD会导致cocos2d帧速率显着下降

时间:2011-10-31 16:28:12

标签: iphone performance cocos2d-iphone ccsprite

我目前正在使用cocos2d为iPhone制作一款游戏并遇到以下问题:

我有一个名为GameHUD的单例类,它在当前级别场景前显示HUD。偶尔我希望重新绘制HUD,因此它会根据当前游戏状态进行相应更改。问题是我重绘HUD的次数越多,帧速率就越低。

我猜我没有发布一些资源,但无法弄清楚我必须释放哪些资源。 (我对内存管理很新。我知道我必须释放使用以下关键字之一创建的对象:“new”,“alloc”,“copy”或“retain”。但是cocos2d主要生成自动释放对象因此,我不能手动释放它们。纠正我,如果我错了;))

//static, so it can be called from other classes
+(void)redrawGameHUD{

CGSize winSize = [CCDirector sharedDirector].winSize;

//get reference to background-sprite
CCSprite *background = [[[GameHUD class] sharedHUD] towerBackground];

//remove the child from the HUD, if it exists
[[[GameHUD class] sharedHUD] removeChild:background cleanup:YES];

//create sprite containing the background-image
background = [CCSprite spriteWithFile:@"background.png"];

//add background image to HUD
[[[GameHUD class] sharedHUD] addChild:background];

//load images that should be displayed into an array
NSArray *images = [NSArray arrayWithObjects:@"image1.png", @"image2.png", @"image3.png", @"image4.png", nil];

//remove sprites from HUD before drawing them again.
//the "buildable" array contains all those already drawn sprites
for (CCSprite *entity in [[[GameHUD class] sharedHUD] buildable]) {
    [[[GameHUD class] sharedHUD] removeChild:entity cleanup:YES];
}
[[[[GameHUD class] sharedHUD] buildable] removeAllObjects];

//loop over sprites, initialize them and add them to the HUD
for(int i = 0; i < images.count; ++i) {

    NSString *image = [images objectAtIndex:i];
    CCSprite *sprite = [CCSprite spriteWithFile:image];

    //add sprite to HUD and memorize them in the "buildable" array
    [[[GameHUD class] sharedHUD] addChild:sprite];
    [[[[GameHUD class] sharedHUD] buildable] addObject:sprite];
}   

}

因此,每次调用此方法时,帧速率会下降一点并保持不变。有人可以告诉我,我做错了什么?感谢。

2 个答案:

答案 0 :(得分:2)

尽量不要在运行时创建和删除sprite,即尽量避免经常这样做:

[CCSprite spriteWithFile:@"background.png"];

这为精灵分配了新的内存,当你创建一个新的精灵时,幕后会发生很多事情。当然,你正在释放已经存在的精灵。所有这些都是不必要的。

在你的redrawGameHUD方法中,我没有看到你为什么要重新创建精灵的迹象。精灵每次都使用相同的图像。那么为什么不保留旧的呢?除非您在将代码发布到问题之前编辑代码,否则无需删除并重新创建HUD精灵。

您可能还想为所有HUD精灵图像创建纹理图集。首先,您可以使用CCSpriteBatchNode通过一次绘制调用渲染所有HUD精灵。其次,每当你想要为现有精灵分配一个新纹理时,你只需要更改该精灵的CCSpriteFrame而不是丢弃精灵并重新创建它。

困扰我的其他事情,你继续写下这个:

[[[GameHUD class] sharedHUD] addChild:sprite];

首先,这与编写以下内容相同,对课程的消息绝对没必要(让我想知道你选择了哪一个?):

[[GameHUD sharedHUD] addChild:sprite];

由于您多次执行此操作,因此应保留GameHUD的临时本地副本,这将再次删除一些不必要的Objective-C消息:

GameHUD* gameHUD = [GameHUD sharedHUD];
// from now on use gameHUD instead of [GameHUD sharedHUD]
[gameHUD addChild:sprite];

这对于循环来说是特别好的建议,因为这样做:

for (CCSprite *entity in [[[GameHUD class] sharedHUD] buildable])

将为可构建数组中的每个实体发送两条额外消息(class和sharedHUD)。这些额外的通话可以很快加起来,虽然它们对你所遇到的帧率下降肯定不够。

您还必须将所有HUD精灵保留在“可构建”数组中。为什么不使用cocos2d使用的现有子数组?只需添加具有相同标签的“可构建”的每个HUD精灵,例如123。

[gameHUD addChild:sprite z:0 tag:123];

如果您需要对所有“可构建的”精灵做一些事情,那么您可以像这样迭代这些孩子:

CCNode* node;
CCARRAY_FOREACH([gameHUD children], node)
{
   if (node.tag == 123)
   {
      CCSprite* buildable = (CCSprite*)node;
      // do stuff with buildable sprite ...
   }
}

同样,这可以避免在可构建数组中不必要地添加,保留,删除和释放对象。并且您可以确定不会意外地从节点层次结构中删除精灵,而不是可构建阵列,反之亦然。

我想以一个假设结束:在你的代码中,我看到了一种普遍的倾向,即你不必要地做了许多额外的事情。所以我猜这是整个项目的情况。你可能想回去问问自己(更好的是:找出)你所拥有的其他东西是不必要的。

答案 1 :(得分:0)

我90%肯定你在iPhone模拟器上测试这个,我是对的吗?

如果您是,请记住,您无法在模拟器上正确分析OpenGL应用程序。性能变化太大。

在真实设备上测试并再次检查帧速率。

如果没有,那么你在其他地方遇到了问题。除非您的图像是5000x5000像素或其他东西,否则在此方法中完成的所有处理都是微不足道的。