0

我目前正在使用 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];
}   

}

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

4

2 回答 2

2

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

[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])

将为可构建数组中的每个实体发送两条额外的消息(类和 sharedHUD)。这些额外的调用会迅速增加,尽管它们肯定不足以解决您正在经历的帧速率下降。

您还不必要地将所有 HUD 精灵保留在“可构建”数组中。为什么不使用 cocos2d 使用的已经存在的 children 数组呢?只需使用相同的标签添加每个“可构建”的 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 ...
   }
}

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

我想以一个假设结束:在您的代码中,我看到了一种普遍趋势,即您正在做许多不必要的额外事情。所以我猜这在整个项目中都是如此。您可能想回去问问自己(最好:找出)您让设备执行的其他一些不必要的事情。

于 2011-10-31T22:05:54.133 回答
0

我 90% 确定您正在 iPhone 模拟器上进行测试,对吗?

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

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

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

于 2011-10-31T20:19:50.010 回答