Cocos2d effects slow down FPS drammatically and how to initialize EAGLView properly

三世轮回 提交于 2019-12-11 14:22:32

问题


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;
}

回答1:


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.




回答2:


I'm not sure if it is the same problem, but after running the CCShaky3D action, my frame rate dropped from 60-50fps to 30-20fps.

I have just managed to solve it creating an action sequence with CCShaky3D and CCStopGrid. The last one is the responsible of recovering the frame rate.



来源:https://stackoverflow.com/questions/10617219/cocos2d-effects-slow-down-fps-drammatically-and-how-to-initialize-eaglview-prope

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!