i am having many plist, in my game-for each level.
i am using this to unload the previous frameCache ,
for(int i=1;i<stage;i++)
[[CCSpriteFrameCache sharedSpriteFrameCache] removeSpriteFramesFromFile:[NSString stringWithFormat:#"candys%i.plist",i]];
but after a while it seems that the game becomes a little bit slower.
i am also loading in real time, the images like this :
sprite = [CCSprite spriteWithSpriteFrameName:[NSString stringWithFormat:#"candy%i.png",1]];
where candy1 is a sprite in a spritesheet on the cache and is being loaded
in REAL time- which mean many times a second.
can it be bad ? is it loads the memory to get the sprite from the spriteSheet many times a second ? do i have to pre define it ?
many thanks .
You don't want to load/unload individual sprite frames. A sprite frame references a texture. Usually this will be a texture atlas which many different sprite frames use. The sprite frame itself is maybe 16 Bytes of data. The texture may be up to 16 Megabytes.
So unless you remove the entire texture atlas and all the associated sprite frames, all you'll be getting is reduced performance because you're frequently deallocating and loading sprite frames. If you do that multiple times per second you're wasting a lot of time just to load/unload sprite frames.
Rule of thumb: load your entire scene up front, keep everything in memory until scene ends. Only if the entire scene doesn't fit into memory at once should you consider unloading/reloading of objects and data.
Related
Developing an iPhone game with Cocos2d-iphone. I have a huge sprite and I want to apply a CCLiquid (or any other liquid-wave-like effect) on it.
However, the image is huge, so it consumes a lot of memory (without mentioning I have many other big elements during gameplay).
Well, I figured I could try to "only apply the liquid effect on the area that is visible by the player" (dimensions of such area being 480x320). That could help a lot.
I already got a CGRect representing the area of the CCSprite that should be affected. However, how would I actually apply the effect only within such area? Any ideas?
You could manually create a CCSprite from a sprite frame and set the boundaries of that frame to your CGRect. Then use the effect on this resulting CCSprite. Essentially, your original CCSprite image would act like a larger texture atlas form which you are specifying a small portion of that image to be the actual frame of your sprite. If you layered this new copied sprite on top of your main, larger one in the exact position, it would appear to be part of that larger sprite, but only the small CGRect portion would be affected by your code.
I used to animate my CCSprites by iterating through 30 image files (rather big ones) and on each file I changed the CCSprite's texture to that image file.
Someone told me that was not efficient and I should use spritesheets instead. But, can I ask why is this not efficient exactly?
There are two parts to this question:
Memory.
OpenGL ES requires textures to have width and height's to the power of 2 eg 64x128, 256x1024, 512x512 etc. If the images don't comply, Cocos2D will automatically resize your image to fit the dimensions by adding in extra transparent space. With successive images being loaded in, you are constantly wasting more and more space. By using a sprite sheet, you already have all the images tightly packed in to reduce wastage.
Speed. Related to above, it takes time to load an image and resize it. By only calling the 'load' once, you speed the entire process up.
in Cocos2d I will be playing an animation. The animation has about 12 frames, and each frame is rather big. In fact, the -hd version of each frame is quite huge.
Anyway, first, I created it by putting all 12 frames in a texture using Zwoptex. The texture is about 2048x2048.
This is so I can animate a CCSprite in a CCSpriteBatchNode using that texture.
But I seem to be getting a level 2 memory warning.
Now that I think of it, I don't think CCSpriteBatchNode was supposed to be used for one sprite. I guess it was only useful if you wanted to draw lots of sprites that use the same texture.
So I want to know: Should I animate the sprite frame by frame (no huge texture)? Or is it possible to use that huge texture but in a different way?
You are right about CCSpriteBatchNode.
CCSpriteBatchNode is like a batch node: if it contains children, it will draw them in 1 single OpenGL call (often known as "batch draw"), in absence of CCSpriteBatchNode (in this case) all the "batch draw" will be called as many time as number of children (sprites).
A CCSpriteBatchNode can reference one and only one texture (one image file, one texture atlas) i.e. sprite sheet created by zwoptex. Only the CCSprites that are contained in that texture can be added to the CCSpriteBatchNode. All CCSprites added to a CCSpriteBatchNode are drawn in one OpenGL ES draw call. If the CCSprites are not added to a CCSpriteBatchNode then an OpenGL ES draw call will be needed for each one, which is less efficient.
According to your scenario, you don't have to use CCSpriteBatchNode since there is only one texture rendered at any given time.
So I want to know: Should I animate the sprite frame by frame (no huge texture)? Or is it possible to use that huge texture but in a different way?
It doesn't matter. You will be loading the 2048 x 2048 texture anyways. The issue to ponder is why only one 2048 x 2048 texture is giving you a Level 2 warning? how many such textures are you loading. BTW 2048 x 2048 is only supported on iPod3G/iPhone3GS above (which is fine).
In case you are loading many textures (which seems true to me). You need to program some logic where you can unload the texture when they are not necessary.
Do look at the following methods:
[[CCSpriteFrameCache sharedSpriteFrameCache] removeSpriteFramesFromFile:fileName];
[[CCSpriteFrameCache sharedSpriteFrameCache] removeUnusedSpriteFrames];
[[CCTextureCache sharedTextureCache] removeUnusedTextures];
As far as animation is concerned you can create CCAnimation and use that or (depending upon your scenario) you can use setDisplayFrame(CCSpriteFrame frame);
I'm developing an iPhone Cocos2D game and reading about optimization. some say use spritesheet whenever possible. others say use atlassprite whenever possible and others say sprite is fine.
I don't get the "whenever possible", when each one can and can't be used?
Also what is the best case for each type?
My game will typically use 100 sprites in a grid, with about 5 types of sprites and some other single sprites. What is the best setup for that? guidelines for deciding for general cases will help too.
Here's what you need to know about spritesheets vs. sprites, generally.
A spritesheet is just a bunch of images put together onto one big image, and then there will be a separate file for image location data (i.e. image 1 starts at coordinate 0,0 with a size of 100,100, image 2 starts at coordinate 100,0, etc).
The advantage here is that loading textures (sprites) is a pretty I/O and memory-alloc intensive operation. If you're trying to do this continually in your game, you may get lags.
The second advantage is memory optimization. If you're using transparent PNGs for your images, there may be a lot of blank pixels -- and you can remove those and "pack" your texture sizes way down than if you used individual images. Good for both space & memory concerns. (TexturePacker is the tool I use for the latter).
So, generally, I'd say it's always a good idea to use a sprite sheet, unless you have non-transparent sprites.
i'm work on a buffer for load very large pictures ( screen size) to single surface.
The idea is to animate a lot of pictures ( more than the video memory can store ) frame by frame.
I have create a code for make a buffer but i have a big problem with the loading time of bitmap.
My code work a this :
I load an array of local bitmap files path.
I (think ) i preload my bitmap datas in memory. I'm using a thread for store a CGImageRef in an NSArray for all my picture ( 40 for moment )
In a second thread, the code look another NSArray for determine if is empty of not, if is empty, i bind my cgimageRef to the video memory by creating textures. ( use sharedgroup for this)
This array store the adress of 20 textures names, and it's use directly by openGL for draw the surface. this array is my (buffer)
When i play my animation, i delete old textures from my "buffer" and my thread ( at point 3) load a new texture.
It's work great, but is really slow, and after few second, the animation lack.
Can you help me for optimise my code ?
Depending on device and iOS version glTexImage is just slow.
With iOS 4 performance was improved so that you can expect decent speed on 2nd gen devices too, and with decent I mean one or two texture uploads per frame...
Anyway:
Use glTexSubImage and reuse already created texture-IDs.
Also, when using glTex(Sub)Image, try to use a texture-ID that wasn't used for rendering in that frame. I mean: add some kind of texture-ID-doublebuffering.
I asume you do all your GL stuff in the same thread, if not change it.