app frame rate is unstable - iphone

Hi all
writing an app for iphone using cocos2d and objective c. i have my frame rate set at 30 fps with
[[CCDirector sharedDirector] setAnimationInterval:1.0/30];
this is fine for awhile but at 1 point in the app the frame rate increases to between 60-90 fps on simulator when swapping between 2 scenes. i put a break point in to get the animationInterval value and it always says it is 0.033 so why would the frame rate be spiking like this?
i have been using
[[CCDirector sharedDirector] stopAnimations]; and
[[CCDirector sharedDirector] startAnimations]; when swapping layers and scenes but i always reset the the interval value when i start it again.
any help would be appreciated
thanks
this is the exact point when the fps goes nuts. when the gamescene is loaded
[[CCDirector sharedDirector] stopAnimation];
GameScene *gameScene = [GameScene node];
[[CCDirector sharedDirector] replaceScene:gameScene];
[[CCDirector sharedDirector] startAnimation];
[[CCDirector sharedDirector] setAnimationInterval:1.0/30];

CCDirector *director = [CCDirector sharedDirector];
[director setAnimationInterval:1.0/60];
[director setDisplayFPS:YES];
Try this to get the exact interval in frames.

Related

how to release cocos2d objects?

I am doing as follows
-(void)Play {
[CCDirector setDirectorType:kCCDirectorTypeDisplayLink];
CCDirector *director = [CCDirector sharedDirector];
//[director setDeviceOrientation:kCCDeviceOrientationLandscapeLeft];
[director setAnimationInterval:1.0/60];
[director setDisplayFPS:NO];
CGRect rect = CGRectMake(0, 0, 320, 480);
EAGLView *glView = [EAGLView viewWithFrame:rect
pixelFormat:kEAGLColorFormatRGB565 // kEAGLColorFormatRGBA8
depthFormat:0 // GL_DEPTH_COMPONENT16_OES
];
[director setOpenGLView:glView];
[window addSubview:glView];
[window makeKeyAndVisible];
[director setDisplayFPS:YES];
[CCTexture2D setDefaultAlphaPixelFormat:kCCTexture2DPixelFormat_RGBA8888];
CCScene *scene = [CCScene node];
CCLayer *layer = [PongLayer node];
[scene addChild :layer];
[[CCDirector sharedDirector] runWithScene: scene];
}
After adding layer to scene, I can go and see screen of PongLayer, but now how to destroy its object when you come back on the main screen from where you start game
I did change layers, but previous layer is working on back end, like if I do put some NSLog that I can see that log yet in running conditions, so what to do?
because when I again call play method, then I don't want to refresh all my array and all data for new scene.
Cocos2d objects such as CCLayer and CCSprite are coded to be auto release objects.
You'll see that the 'node' method alloc's inits and autoreleases an object when it's created.
Methods such as 'spriteWithFile:' and 'layerWithColor:' also are coded with autoreleased.
When you add an object as a child to a Layer or any other node for that matter, it creates a pointer to the object, retaining it. When the object is removed as a child, it deallocates itself.
So, when you move from Scene to Scene, the scene that is removed, deallocates it's children (layers) and they in turn their children (sprites).
http://www.cocos2d-iphone.org/wiki/doku.php/start
The only exception is when you create a sprite like this..
CCSprite *mySprite = [CCSprite alloc] init];
You have personally allocated and initialized this sprite, you must release it.
If you have CCLog turned on, it logs out when CCSprites are deallocated.
Another small thing worth mentioning, Scene's won't deallocate themselves if you 'push' the scene, only popping and replacing scene's cause 1 to deallocate.

cocos2d add a 'ready-go!' animation before the game

I want to add a 'ready-go!' animation before game, as well as during game (need to pause the game)
i tried to use [CCDirector sharedDirector] pushScene: [Anim scene]], but although the background of Anim scene is smaller than window size, the transparent area is black instead of see through the scene below.
how can i implement it? (or i don't have to use pushScene at all? )
here is the code for GameScene, onEnter i schedule the 'count' (timer), onExit i unschedule it.
-(void) onEnter {
GameManager* sharedManager = [GameManager sharedManager];
[[CCScheduler sharedScheduler] scheduleSelector:#selector(count) forTarget:sharedManager interval:1.0f paused:NO];
[super onEnter];
}
- (void)onExit {
GameManager* sharedManager = [GameManager sharedManager];
[[CCScheduler sharedScheduler] unscheduleSelector:#selector(count) forTarget:sharedManager];
[super onExit];
}
problem solved. I just create a scene specifically for the 'ready-set-go' animation, pass the necessary parameters to the AnimationScene, then launch the game from the AnimationScene using scheduler.
The result is not as good as 'ready-go' sign on top of GameScene since i am not able to make the transparent effect, but i tried to mimic the background of game scene, and it turns out quite well.
- (void)pauseButtonTapped {
[[CCDirector sharedDirector] pause];
[self pauseSchedulerAndActions];
}
- (void)playButtonTapped {
[[CCDirector sharedDirector] resume];
[self resumeSchedulerAndActions];
}
CCSequence. Before enabling AI timers or whatever runs your game objects, run a CCSequence action.

iPhone Cocos2d game change to iPad game

I have spent 1000's of hours into one of my games and just started looking at iPad stuff. Yeah... didn't realize what the whole CGSize size = [[CCDirector sharedDirector] winSize]; thing was until now.
So I'm pretty much screwed right? There's no sense in changing literally 10,000 ccp coordinates?
Is there a way:
if iPad
add or subtract to the ccp to position to put everything in the center
I could add it to every scene.
Yes no worries. I believe you just need to change your assets and just define:
float deviceScale
And you can easily check in your appDelegate, what device is the program running on:
NSString *deviceType = [UIDevice currentDevice].model;
NSLog(#"deive name is %#",deviceType);
if([deviceType isEqualToString:#"iPad"] || [deviceType isEqualToString:#"iPad Simulator"] ){
[[CCDirector sharedDirector] setContentScaleFactor:1];
} else {
if([[UIScreen mainScreen] respondsToSelector:NSSelectorFromString(#"scale")])
{
if ([[UIScreen mainScreen] scale] < 1.1){
[[CCDirector sharedDirector] setContentScaleFactor:1];
}
if ([[UIScreen mainScreen] scale] > 1.9){
//retina display
[[CCDirector sharedDirector] setContentScaleFactor:2];
}
}
else {
[[CCDirector sharedDirector] setContentScaleFactor:1];
}
}
As I said before you might need to have a variable 'deviceScale', for retina/ ipad make it deviceScale = 1 for all others deviceScale = 0.5. Then scale down the images if device is non retina or not ipad.
I hope your app is using version 0.99.5. 0.99.5 is using by pixels or something.. So you wont b screwed. It will auto scale by ratio.. No worries..

How can we set time delay in animation of images to make them appear smooth?

I have 10 CCSprite images. They are continues images. I am using,
CCSprite *playerH = [CCSprite spriteWithFile:#"Player_01.png" ];
playerH.position = ccp(playerH.contentSize.width/2, windowSize.height/2);
[self addChild:playerH z:1];
CCAnimation* animation = [CCAnimation animationWithName:#"dance" delay:0.20f];
for( int i = 1; i < 11; i++ )
{
[animation addFrameWithFilename: [NSString stringWithFormat:#"Player_%02d.png", i]];
}
NSLog(#"k VALUE: k: %d",k);
id actionA = [CCAnimate actionWithAnimation: animation restoreOriginalFrame:NO];
id actionD = [CCDelayTime actionWithDuration:5.0f];
id actionC = [CCCallFunc actionWithTarget:self selector:#selector(enemyEntranceScreen:)];
id seqActionPlayer = [CCSequence actions:actionA, actionD, actionC, nil];
[playerH runAction: seqActionPlayer];
But the animation is not continues. I have changed the animation delay time. but, I can see only three images appearing. How can we know how much time interval should we keep in animation.
Is there any relationship between this and the frame rate
[[CCDirector sharedDirector] setAnimationInterval:1.0/60];
[[CCDirector sharedDirector] setDisplayFPS:YES];
Thank you.
I got my animation smoothly. I think it depends on the
[[CCDirector sharedDirector] setAnimationInterval:1.0/60];
[[CCDirector sharedDirector] setDisplayFPS:YES];
Previously the setAnimationInterval value is 60.0/60. I changed it to 1.0/60. I could find all the images when the value is 1.0/60. I adjusted the animation time delay between the images.
But, when setAnimationInterval is 60.0/60 even I set the value of animation delay to 1second, I could not see all the 10 images displayed.
But, I need some clarification on the setAnimationInterval:
Thank You.

UIScrollView and Cocos2D

I have created a UIScrollView in a cocos2d application. I am adding sprites dynamically, over 3 pages. On the first page, touch works perfectly on a sprite, however if I use the scroll view and navigate to the second page, touch does not work quite right... the sprite will respond to the touch when I touch the screen, approximately the amount I have scrolled to the left. If I scroll back to the first page, touch works perfectly for a sprite. Any ideas? I am using the following tutorial: http://getsetgames.com/2009/08/21/cocos2d-and-uiscrollview/ :)
I think some code might be useful:-
I am using the exact code from your demo...
CocosOverlayScrollView and CocosOverlayViewController
I am creating the CocosOverlayViewController in my layer:-
CocosOverlayViewController *scrollView = [CocosOverlayViewController alloc];
[[[Director sharedDirector] openGLView] addSubview:scrollView.view];
I am creating the layer in my scene:-
Scene *scene = [Scene node];
GridLayer *layer = [GridLayer node];
[scene addChild: layer z:-1];
[scene setTag:12];
I am creating the sprites in my layer:-
myImage.position = ccp(53 * (coordinate.x + 0.52), 57 * (coordinate.y + 1.45));
[myImage runAction:[FadeIn actionWithDuration:0.3]];
myImage.relativeAnchorPoint = YES;
[self addChild:myImage z:-1];
The sprite is using the TouchesDispatcher and the touches are resolved in the class.
If I use the cocos2d moveto function on the layer I can touch a sprite and it responds so I know it works, things just get a little odd when I use the UIScrollView.
I hope you understand my problem and can help, all the best :)
Carl
I finally got to implementing scrolling of a CCLayer by using a UIScrollView derived class, following the tutorials mentioned in this question:
http://getsetgames.com/2009/08/21/cocos2d-and-uiscrollview/
http://www.cocos2d-iphone.org/forum/topic/9417
Both of them are an excellent read, and highly recommended to get a deeper understanding about how UIScrollViews (and UIViews in general) can be made to handle touches in cooperation with Cocos2D.
However, upon implementing these solutions, I also experienced the bug described in the question: if you don't scroll, touches are propagated from the UIScrollView to the CCLayer correctly. If you scroll, the layer scrolls beautifully but non-scrolling touches on the UIScrollView propagate to the CCLayer with an offset that grows the more you scroll, which makes the CCLayer (and/or accompanying CCMenus) unusable.
I have found the cause of this problem to be a bug in how Cocos2D translates touches sent to the OpenGLView to the local CCNode or CCMenu coordinate systems. This bug is present in 1.0 rc, and only affects touches that are generated on a OpenGLView's subview (like our UIScrollView) and get propagated to the Cocos2D main touching area (namely the OpenGLView) by calling the following line inside the UIScrollView's -touchesBegan: method
[[[CCDirector sharedDirector] openGLView] touchesBegan:touches withEvent:event];
(Note that calling this previous line is enough for propagating nonscrolling and nonzooming touches from the UIScrollView to Cocos2D, you do not need to call nextResponder: as the aforementioned blog posts do.)
The solution comes with a small modification on two Cocos2D sources:
CCNode.m
- (CGPoint)convertTouchToNodeSpace:(UITouch *)touch {
// cocos2d 1.0 rc bug when using with additional overlayed views (such as UIScrollView).
// CGPoint point = [touch locationInView: [touch view]];
CGPoint point = [touch locationInView: [[CCDirector sharedDirector] openGLView]];
point = [[CCDirector sharedDirector] convertToGL: point];
return [self convertToNodeSpace:point];
}
- (CGPoint)convertTouchToNodeSpaceAR:(UITouch *)touch {
// cocos2d 1.0 rc bug when using with additional overlayed views (such as UIScrollView).
// CGPoint point = [touch locationInView: [touch view]];
CGPoint point = [touch locationInView: [[CCDirector sharedDirector] openGLView]];
point = [[CCDirector sharedDirector] convertToGL: point];
return [self convertToNodeSpaceAR:point];
}
CCMenu.m
-(CCMenuItem *) itemForTouch: (UITouch *) touch {
// cocos2d 1.0 rc bug when using with additional overlayed views (such as UIScrollView).
// CGPoint touchLocation = [touch locationInView: [touch view]];
CGPoint touchLocation = [touch locationInView: [[CCDirector sharedDirector] openGLView]];
touchLocation = [[CCDirector sharedDirector] convertToGL: touchLocation];
...
The key here is UITouch's locationInView: method. The argument for this method should be the UIView that you want to translate the touches coordinates into. Most Cocos2D project only have one UIView: the OpenGLView, so touches get generated in the OpenGLView (= touch view) and get translated to the same view. However, if you add overlaying subviews to receive touches, such as a UIScrollView, 'touch view' will have this value, which no longer corresponds to the desired OpenGLView.