CCRenderTexture saveToFile takes up a large amount of memory - cocos2d-iphone

I'm working on a game and I want to create thumbnails of each level so I can use them in a menu. I do this with CCRenderTexture like this:
CCRenderTexture *renderer = [CCRenderTexture renderTextureWithWidth:bounds.size.width height:bounds.size.height];
ScreenShotLayer *scene = [[ScreenShotLayer alloc] init];
[renderer begin];
[scene visit];
[renderer end];
[renderer saveToFile:[NSString stringWithFormat:#"level%#.png", level.levelId] format: kCCImageFormatPNG];
This all works well and my image is saved, but it takes up a huge amount of memory and never releases it. Without saving this data my game takes 8 MB of RAM. When I save the image it takes over 430 MB.
If I leave everything the same and just comment out the saveToFile call I'm back to my 8 MB memory usage. I've debugged this with the leaks tool and it doesn't find any leaks.
Is this a framework issue? Is there a better way to handle this? Am I doing something silly?
My whole game is open source and you can get it at https://github.com/zgrossbart/bridges. This code happens in LevelMgr.mm.
Thanks for the help,
Zack

I found a solution to this problem on the Cocos2d forum and with a bit of poking around the code. You can read the forum post her:
http://www.cocos2d-iphone.org/forum/topic/48890
I still see CCRenderTexture leak a little memory. The Cocos2d team has tested this and says it's working in 2.1-beta. There's also a big performance improvement I could have made to my code.
I was using CCRenderTexture to create a thumbnail image of a Cocos2d scene. I did that by using CCRenderTexture to create a full size image and then using a special UIImage to resize and crop the image. It's much more efficient to create a CCRenderTexture of the size I want in the end and scale my Cocos2d scene to the size I want in the end.

Related

Strange artefacts appear on CCSprite

I have a CCLayer class imported onto a game layer
strangely all the the sprites have "artefacts" that seem to appear from nowhere since I have checked and re-exported all of the files
Is some setting or something else that could cause this to happen?
I'm new at this
but I have checked so far:
set to PixelFormat_RGBA8888
PVRImagesHavePremultipliedAlpha:YES
png's are clear from artefact (28bit with transparency)
Textures are made with texture packer with "pre-multiplied"
The Background is a CCLayer
The Mine is a CCLayer
both are added to the game layer (cclayer also) as "addChild"
backgroundManager = [[BackGround alloc] init];
[self addChild:backgroundManager z:0];
myShip = [[Ship alloc]init];
[self addChild:myShip z:5];
Yes it was the settings in texture packer
after a few changes in the settings they now seem to load fine.
with no artifacts
use pre multiple
trim not crop
and give a little more inner padding
hope it helps someone else (since it was driving me a little crazy)

Take few seconds to load the scene cocos 2d

I have used
[[CCDirector sharedDirector] replaceScene:[CCBReader sceneWithNodeGraphFromFile:#"SongScene.ccbi"] ];
For load the next scene. It take a little delay to load the scene. When the second time loading, there is no delay. How can i fix the issue. Songs scene consist of many graphic sprites.
When you first start your game, create an Intro Scene showing a splash image or loading image, etc. While that scene is showing, load up the resources that will take a long time to load so that they are already in the cache.
When they are done loading, transition to your main scene(s). The resources will already be loaded and they will go faster.
You can even create entire scenes like this, you just need a place to store them off temporarily, such as the child of a CCNode that you use for holding scenes. Then use them when you need them.
I only learned this recently. Before that I was loading them at the start of the App, which is a poor choice.

How to load the loading scene background in cocos2d without blanking out?

I have a cocos2d game that has a loading scene where we load a bunch of assets. The game starts with the splash screen, and then launches the loading scene. The loading scene starts by loading the background, so the user sees the loading scene background while the assets are being loaded.
I load the loading scene background by calling CCSprite::spriteWithFile: and passing the filepath: loadingbackground.pvr.ccz
It seems to work differently on different devices:
On iphone (3gs) simulator, I see the loading scene as expected.
On iphone retina simulator, I don't see the loading scene (there aren't many assets yet, so may be happening quickly) and it goes directly to the main menu scene.
On the ipad 3 device, the splash screen comes up, and then there is a half second of black screen, and then the main menu scene shows up.
I want to see what I can do to avoid that black screen showing up on iPad 3. I suspect this is because of the time taken to load the loading background.
I have tried the following optimizations (mostly based on #Steffen's blog post on memory optimization):
Moved the loading background (originally 2.3 MB RGB8 png file) into a pvr.ccz spritesheet by itself, which reduced its size to 1.8 MB.
Removed the image from the texture soon after use.
I still see a black screen on iPad 3. Any suggestions?
Update: Found the issue - I had some code where I was overriding OnEnter and calling [[CCDirector sharedDirector]replaceScene] in it, and also calling the same from the background thread. Removed the OnEnter overload and it worked without flicker.
Thanks
Ignore whatever happens in Simulator. That's not relevant, focus on the device.
When the loading scene initializes and you add the loading scene's background, make sure you schedule update and load your assets in the update method. Otherwise if you load the assets in init, the background won't be drawn because you're loading all the assets before cocos2d gets to redraw the screen.
If this still fails, simply send the visit message to the background sprite followed by [[CCDirector sharedDirector] drawScene]. This forces a redraw of the scene.
Is this cocos2d-iphone or cocos2d-x ? make sure the tags are correct :)
I think you're referring to the startup flicker, there are a few ways to avoid that.
first thing you need to make sure you're handling the rootViewController correctly for iOS 6 and iOS 5 and below, there are a little changes for each.
You can find a little reference here:
http://www.cocos2d-iphone.org/forum/topic/34471
Second thing you need to know that simulator's behaviour is not stable, you should always rely on real devices for testing, but it's very likely you'll still have the flicker issues.
Sorry I didn't provide example code, but you haven't supported enough information to know what's the real issue here.

cocos2d - Replacing cached sprite image

I'm new to cocos2d. I've been following a tutorial which I've got working but when I updated the image I used to shoot fireballs by deleting and replacing it from the resources folder, the image no longer renders. What do I have to do when replacing an image?
Before I swapped the images:
CCSprite *projectile = [CCSprite spriteWithFile:#"Projectile.png"
rect:CGRectMake(0, 0, 20, 20)];
After swapping images:
CCSprite *projectile = [CCSprite spriteWithFile:#"Fireball.png" rect:CGRectMake(0, 0, 20, 20)];
Do I need to delete the cache somehow and re-add the image?
EDIT:
I added this line below my code and it worked:
[projectile setTexture:[[CCTextureCache sharedTextureCache]
addImage:#"Fireball.png"]];
Strange how I have to add a new line of code to replace an image.
I find that sometimes i need to clean and build for the updated texture to finally make it to the app's bundle ... (I suspect this happens when i change a resource while the app is running, but frankly i have lost too much time with this to investigate). Now i de-facto clean and build when changing resources.
I am not certain this is a 'cocos2d' discussion, but rather an Xcode one. The cocos2d texture cache is entirely constructed in memory, during the execution of your app. It is a mechanism that 1) helps keep the memory footprint smaller, and 2) also boosts performance since a texture file is only loaded once if you dont clear the cache. Xcode on the other hand keeps copies of all your files in multiple places. By 'cleaning' a build, you ensure that previous versions of files are removed, and all the current resources (including textures) are placed in the appropriate places for the development environment to function properly.

How do you animate in Cocos2d?

I am trying to animate a sprite. The cocos2d website makes it look so easy but everytime I try it I get errors. I managed to download some code to get it working but one sprite animation takes 6 files. I have a character that needs to walk right and left, jump, climb, and fall. That means I am looking at 35 files. can't it be streamlined a bit? It just seems way harder than it should be.
Thanks,
Josh
Cocos is great. You just need to spend time with the demo project, hang out on the message board, and keep at it.
You animate a sprite like this:
id action = [Sequence actions:
[ScaleTo actionWithDuration:.3 scale:0.7f],
[ScaleTo actionWithDuration:.3 scale:1.0f],
nil];
[[self getByTag:FOO] do:action];
This causes the sprite with the tag FOO to scale down to 70 percent in .3 seconds, then back up to 100 percent in .3 seconds.
Much more complex animations are possible, just get the basics down and the world will be ya oyster, at least as far as making stuff fly around on the screen, that is.
UIImageView* headBandAnimation = [[UIImageView alloc] initWithFrame:CGRectMake(25, 205, 100, 50)];
headBandAnimation.animationImages = [NSArray arrayWithObjects:
[UIImage imageNamed:#"band1.png"],
[UIImage imageNamed:#"band2.png"],
[UIImage imageNamed:#"band3.png"],
[UIImage imageNamed:#"band4.png"], nil];
headBandAnimation.animationDuration = 0.5;
headBandAnimation.animationRepeatCount = 0;
[headBandAnimation startAnimating];
[self.view addSubview:headBandAnimation];
is how to do animation without cocos2d if you wish to go this route.
Cocoa With Love have a short-series on writing a came using CoreAnimation, perhaps it might be of use?
Cocoa does take a lot of getting used to, and does seem really overly convoluted, but when you compared it to.. well, most other GUI toolkits I've used, it suddenly seems very elegant and simple. The problem with the example code, and most tutorials (including the one I linked to, albeit to a slightly lesser degree) is they only show you the finished application - it doesn't show the increments. There's no "I have a empty canvas", then "I worked out how to draw a circle", then "I've animated the circle".
Try making a new application, look through the example code/IB project/tutorials/documentation for the bit that initialises the canvas-thing. Then look for the code that adds a simple shape. Then look for the code to animate the code (Genericrich answer, for example)
I know this thread is much older, but for future reference this is the article which seems best fit for this question.
It involves TexturePacker tool which generates a PLIST and a PNG that fulfill our needs.