0

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;
}
Community
  • 1
  • 1
mm24
  • 9,280
  • 12
  • 75
  • 170

2 Answers2

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.

YvesLeBorg
  • 9,070
  • 8
  • 35
  • 48
  • Hi, thanks for this. I'll try to add the command after lunch :). In the meanwhile, those framerates refer to real device data. I'll post back soon after trying playing with the memory management. Thanks! – mm24 May 16 '12 at 12:31
  • PS: Do you animate the sprites using the Effects? Also, could I ask you how you handle the sprites? Do you have a EnemyCache class with an array or do you add and remove them to the scene according to when they are supposed to appear? PPS: I did try to use your commands and it removes texture cache data that I needed (e.g. bullet frames which I had loaded in the game scene). I probably need to work on my memory management better if you can confirm that you are able to run 3D effects on 16 animated sprites your app. – mm24 May 16 '12 at 13:02
  • I added an EDIT2 with source code of the TestLayer I created to try test our assumptions. There is evidence that running the CCShaky3D effect on more than one CCSprite simultanuesly is enough to drop the frame rate.. unless I am missing out something trivial in my test case. – mm24 May 16 '12 at 14:22
  • Unfortunately not effects, i'm rather old hat with respect to stuff like performance, and tend to have as much control as possible over the various elements that may affect it. I add sprites 'just in time', and remove them as early as possible. I prefer to re-incur the cost of loading again and again sprites than having extra baggage in memory. Typically the load is in a logical game 'pause', during a transition, or some other circumstance that would not be a deterrent to gamer experience. – YvesLeBorg May 16 '12 at 15:44
  • Unfortunately not effects, i'm rather old hat with respect to stuff like performance, and tend to have as much control as possible over the various elements that may affect it. I add sprites 'just in time', and remove them as early as possible. I prefer to re-incur the cost of loading again and again sprites than having extra baggage in memory. Typically the load is in a logical game 'pause', during a transition, or some other circumstance that would not be a deterrent to gamer experience. – YvesLeBorg May 16 '12 at 15:45
  • Thank you. To understand better.. in case you have a shooter game, how would you handle the repeating enemies? E.g. four instances of the same space ships might appear at the beginning of one game scene and ten more might appear at the end of the scene, would you still load and unload or would you create a max number of sprites (e.g. 10) and modify the position and visibility of those instead of deallocating-reallocating (recycling) – mm24 May 17 '12 at 07:34
  • PS: I haven't yet accepted the answer as I'd like to see if someone had the same performance problem with using the 3D effects. – mm24 May 17 '12 at 07:34
  • @YvesLesBorg sorry for taking time to accept the answer, I did find it useful and helped me reasoning on FPS and getting my head around the issue :). Thanks! – mm24 Jun 15 '12 at 08:17
1

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.

Veger
  • 37,240
  • 11
  • 105
  • 116
Jon
  • 23
  • 6