Cocos2d效果慢慢减慢FPS和如何正确初始化EAGLView [英] Cocos2d effects slow down FPS drammatically and how to initialize EAGLView properly

查看:370
本文介绍了Cocos2d效果慢慢减慢FPS和如何正确初始化EAGLView的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

EDIT2:为了回答下面的答案,我创造了一个不同的GameScene测试帧速率性能与4个精灵由CCShaky3D效果动画。问题仍然存在,因为fps仍然在〜15fps。我粘贴在这个问题的结尾的代码,以方便阅读。我的假设是,这是因为我在同一时间运行多个CCShaky3D的事实。是否有人能够同时运行多个CCShaky3D效果而不降低帧速率?



我引入了Effects( cocos2d编程指南)来自cocos2d在我的游戏,并注意到FPS drammatically减慢。



我已经在我的游戏中介绍过它们,并且有黑色背景问题(如后所以帖子)。我按照解决方案,问题解决了。



我注意到在调试器,一旦第四个精灵,我应用的动画出现应用程序接收内存警告。一旦我应用效果的第二个sprite变得可见,帧速率就会下降。在现场我已经有其他2-3敌人精灵在屏幕上同时加上播放器精灵,我猜这可能是一个内存问题。然后我试图添加只有一个精灵动画和剩余的2-3个敌人精灵仍然存在,帧速率下降只到〜45 fps。



编辑:当我不对这些精灵应用效果时,帧速率不变(保持〜60fps)。 p>

我想这是由于我如何管理我的记忆,但在改变代码之前,我想收集一些意见。你设法用eg运行一个场景。

正确初始化EAGLView p>

为了获得运行的效果我不得不修改 EAGLView 初始化我发布在这里,因为我认为可能是ralated。我非常不熟悉UIViewController和EAGLView初始化,我想知道如果我做错了一些,如果这可能会影响帧率。



我修改了ShootEmUp示例了解iPhone和iPad cocos2d第8章源代码,并注意到示例的AppDelegate没有RootViewController 实例。相反,在 Coco2d Cookbook 中,在AppDelegate以及我使用Cocos2d创建的任何模板中都使用了RootViewController。在我的代码中,我修改了CC_DIRECTOR_INIT()宏,添加了EAGLView的初始化,如后 2 < a>。



我发现这个官方cocos2d指南,说明没有必要在cocos2d应用程序中创建UIViewController,它确认ShootEmUp示例中的方法( 3 )。因为我仍然不熟悉CCDirector,EAGLView和UIViewController的角色,我想要求澄清他们如何互相交互,以及任何这些的初始化可能会影响帧速率。非常感谢。



EDIT 2 - 用于测试CCShaky3D效果对fps效果的源代码:

  // Element.h 
#import< Foundation / Foundation.h>
#importcocos2d.h

@interface元素:CCSprite {

}
+(id)elementWithTypeAndSpawnTimeAndFrameNameAndSpawnPos :( enum ElementsType)type: (int)time:(NSString *)frameName:(CGPoint)spawnPosition;
@end


//实现elementWithTypeAndSpawnTimeAndFrameNameAndSpawnPos方法..
+(id)elementWithTypeAndSpawnTimeAndFrameNameAndSpawnPos:(enum ElementsType)type:(int)time:(NSString * )frameName:(CGPoint)spawnPosition;
{
return [[[self alloc] initWithTypeAndSpawnTimeAndFrameNameAndSpawnPos:type:time:frameName:spawnPosition] autorelease];
}

//TestLayer.h
#import< Foundation / Foundation.h>
#importcocos2d.h
@interface TestLayer:CCLayer {

}
+(CCScene *)场景;
@end


//TestLayer.m

#importTestLayer.h
#importElement.h

@implementation TestLayer


+(CCScene *)场景
{
//'scene'是一个自动释放对象。
CCScene * scene = [CCScene node];

//'layer'是一个autorelease对象。
TestLayer * layer = [TestLayer node];

//将图层作为子级添加到场景
[scene addChild:layer];

//返回场景
return scene;
}

/ oninit你需要初始化你的实例
- (id)init
{
//总是调用superinit
// Apple建议重新分配self与super返回值
if((self = [super init])){
CCSpriteFrameCache * frameCache = [CCSpriteFrameCache sharedSpriteFrameCache] ;
[frameCache addSpriteFramesWithFile:@game-art-hd.plist];

//问导演的窗口大小
CGSize size = [[CCDirector sharedDirector] winSize];

CCSprite * background = [CCSprite spriteWithFile:@bg1.png];
background.anchorPoint = CGPointMake(0.5f,0);
background.position = CGPointMake(size.width / 2,0);
[self addChild:background];

Element * element = [Element elementWithTypeAndSpawnTimeAndFrameNameAndSpawnPos:HEARTH:3:@star-anim1.png:CGPointMake(100.0f,20.0f)];
element.visible = TRUE;
id shaky = [CCShaky3D actionWithRange:4 shakeZ:NO grid:ccg(15,10)duration:5];
[element runAction:shaky];
[self addChild:element];

element = [Element elementWithTypeAndSpawnTimeAndFrameNameAndSpawnPos:HEARTH:3:@star-anim1.png:CGPointMake(140.0f,20.0f)];
id shaky2 = [CCShaky3D actionWithRange:4 shakeZ:NO grid:ccg(15,10)duration:5];

element.visible = TRUE;
[element runAction:shaky2];
[self addChild:element];

element = [Element elementWithTypeAndSpawnTimeAndFrameNameAndSpawnPos:HEARTH:3:@star-anim1.png:CGPointMake(240.0f,20.0f)];
element.visible = TRUE;
id shaky3 = [CCShaky3D actionWithRange:4 shakeZ:NO grid:ccg(15,10)duration:5];

[element runAction:shaky3];
[self addChild:element];


element = [Element elementWithTypeAndSpawnTimeAndFrameNameAndSpawnPos:HEARTH:3:@star-anim1.png:CGPointMake(340.0f,20.0f)];
element.visible = TRUE;
id shaky4 = [CCShaky3D actionWithRange:4 shakeZ:NO grid:ccg(15,10)duration:5];

[element runAction:shaky4];
[self addChild:element];

}
return self;
}


解决方案

在真实设备上运行?你应该知道,模拟器下执行与真实设备相比的显着因素。我目前运行一个应用程序与16+动画精灵在战斗场景,在非常不错的帧速率装置...但在模拟器上10 FPS以下。是的,注意那个记忆警告。你可能有精灵,不会在某处正确解除分配。为了确认这一点,你应该在代码中的适当位置添加这一行:

  [[CCSpriteFrameCache sharedSpriteFrameCache] removeUnusedSpriteFrames] ; 
[[CCDirector sharedDirector] purgeCachedData];
[[CCTextureCache sharedTextureCache] dumpCachedTextureInfo];

并验证您在纹理缓存中有什么对应于您的期望。如果没有,请追逐惊喜纹理,并确保它们被正确删除。


EDIT2: In response to the answer below I did create a different GameScene for testing the framerate performance with 4 sprites animated by a CCShaky3D effect. The problem still persist as the fps is still around ~15fps. I paste the code at the end of this question to facilitate reading. My assumption is that is due to the fact that I am running more than one CCShaky3D at the same time. Is anyone able to run multiple CCShaky3D effects at the same time without frame rate drop?

I introduced Effects (cocos2d programming guide) from cocos2d in my game and noticed that the FPS drammatically slow down. From 60fps to ~10fps once the sprite on which I apply the effect appear.

I had introduced them in my game at first and had the black background problem (as in post so post). I followed the solution and the problem was solved.

I noticed in the debugger that once the fourth sprite to which I apply the animation appears the Application receives memory warning. The frame rate drops as soon as the second sprite to which I apply the Effect becomes visible. In the scene I have already other 2-3 enemy sprites in the screen at the same time plus the player sprite and I guess this might be a memory issue. I then tried to add only one sprite with animation and the remaining 2-3 enemy sprites are still there and the frame rate drops "only" to ~45 fps.

EDIT: When I don't apply the effect to those sprites the frame rate doesn't change (stays ~60fps).

I guess this is due on how I manage my memory but before changing drammatically the code I wanted to gather some opinion on this. Do you manage to run a scene with eg. 2-3 sprites with an effect and 4-5 other sprite (e.g. enemies and player) moving around?

Initializing EAGLView properly:

As to get the Effects running I had to modify EAGLView initialization I post this here as I think might be ralated. I am very unfamiliar with UIViewController and EAGLView initialization and I am wondering if I am doing something wrong on it and if this could affect the framerate.

I modified the ShootEmUp example from Learn iPhone and iPad cocos2d chapter 8 source code and noticed that in the example's AppDelegate there is no RootViewController instance. Instead in Coco2d Cookbook a RootViewController is used in the AppDelegate as well as in any template that I create using Cocos2d. In my code I modified the CC_DIRECTOR_INIT() macro adding the initialization of EAGLView as suggested in post 2.

I found this official cocos2d guide which says that there is no need to create UIViewController in a cocos2d application which confirms the approach in ShootEmUp example (3). As I am still unfamiliar with the roles of CCDirector, EAGLView and UIViewController I'd like to ask for a clarification to the commmunity on how they interact with each other and also if the initialization of any of those can affect the frame rate. Thanks a lot.

EDIT 2 - Source code that I used for testing the CCShaky3D effect effect on fps performance rate :

// Element.h
#import <Foundation/Foundation.h>
#import "cocos2d.h"

@interface Element : CCSprite {

}
+(id) elementWithTypeAndSpawnTimeAndFrameNameAndSpawnPos:(enum ElementsType)type:  (int)time  :(NSString*)frameName :(CGPoint) spawnPosition;
@end


//Implementation of elementWithTypeAndSpawnTimeAndFrameNameAndSpawnPos method.. 
+(id) elementWithTypeAndSpawnTimeAndFrameNameAndSpawnPos:(enum ElementsType)type:  (int)time  :(NSString*)frameName :(CGPoint) spawnPosition;
{
    return [[[self alloc] initWithTypeAndSpawnTimeAndFrameNameAndSpawnPos:type :time :frameName :spawnPosition] autorelease];
}

//TestLayer.h
#import <Foundation/Foundation.h>
#import "cocos2d.h"
@interface TestLayer : CCLayer {

}
+(CCScene *) scene;
@end


//TestLayer.m

#import "TestLayer.h"
#import "Element.h"

@implementation TestLayer


+(CCScene *) scene
{
    // 'scene' is an autorelease object.
    CCScene *scene = [CCScene node];

    // 'layer' is an autorelease object.
    TestLayer *layer = [TestLayer node];

    // add layer as a child to scene
    [scene addChild: layer];

    // return the scene
    return scene;
}

/ on "init" you need to initialize your instance
-(id) init
{
    // always call "super" init
    // Apple recommends to re-assign "self" with the "super" return value
    if( (self=[super init])) {
        CCSpriteFrameCache* frameCache = [CCSpriteFrameCache sharedSpriteFrameCache];
        [frameCache addSpriteFramesWithFile:@"game-art-hd.plist"];

        // ask director the the window size
        CGSize size = [[CCDirector sharedDirector] winSize];

        CCSprite *background = [CCSprite spriteWithFile:@"bg1.png"];
        background.anchorPoint = CGPointMake(0.5f, 0);
        background.position = CGPointMake(size.width/2, 0);
        [self addChild:background];

        Element * element = [Element elementWithTypeAndSpawnTimeAndFrameNameAndSpawnPos:HEARTH :3 :@"star-anim1.png" :CGPointMake(100.0f, 20.0f)];
        element.visible=TRUE;
        id shaky = [CCShaky3D actionWithRange:4 shakeZ:NO grid:ccg(15,10) duration:5];
        [element runAction:shaky ];
        [self addChild:element ];

        element = [Element elementWithTypeAndSpawnTimeAndFrameNameAndSpawnPos:HEARTH :3 :@"star-anim1.png" :CGPointMake(140.0f, 20.0f)];
        id shaky2 = [CCShaky3D actionWithRange:4 shakeZ:NO grid:ccg(15,10) duration:5];

        element.visible=TRUE;
        [element runAction:shaky2 ];
        [self addChild:element ];

        element = [Element elementWithTypeAndSpawnTimeAndFrameNameAndSpawnPos:HEARTH :3 :@"star-anim1.png" :CGPointMake(240.0f, 20.0f)];
        element.visible=TRUE;
        id shaky3 = [CCShaky3D actionWithRange:4 shakeZ:NO grid:ccg(15,10) duration:5];

        [element runAction:shaky3 ];
        [self addChild:element ];


        element = [Element elementWithTypeAndSpawnTimeAndFrameNameAndSpawnPos:HEARTH :3 :@"star-anim1.png" :CGPointMake(340.0f, 20.0f)];
        element.visible=TRUE;
        id shaky4 = [CCShaky3D actionWithRange:4 shakeZ:NO grid:ccg(15,10) duration:5];

        [element runAction:shaky4 ];
        [self addChild:element ];

    }
    return self;
}

解决方案

What FPS did you obtain when running on a real device ? You should know that the simulator under performs compared to real devices by significant factors. I currently run an app with 16+ animated sprites in a fight scene, at very decent frame rates ON DEVICES ... but under 10 FPS on simulator. And yes, pay attention to that memory warning. You probably have sprites that dont get deallocated properly somewhere. In order to confirm this, you should add this line at an appropriate place in your code:

    [[CCSpriteFrameCache sharedSpriteFrameCache] removeUnusedSpriteFrames];
    [[CCDirector sharedDirector] purgeCachedData];
    [[CCTextureCache sharedTextureCache] dumpCachedTextureInfo];

and verify that what you have in the texture cache corresponds to what you expect. If it does not, chase down the 'surprise' textures and make certain they are removed properly.

这篇关于Cocos2d效果慢慢减慢FPS和如何正确初始化EAGLView的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆