I just randomly stumbled upon some answer: https://stackoverflow.com/a/3923131/555690 which states
How memory leakage is solved: [...]
if you switch scene from outside of scheduled selector or there is more than one scheduled
selector then you must unschedule before switching.
Is there any truth to that? I'm skeptical because when a scene is replaced, I'd imagine that it is dealloced, and when that happens it is only logical (to me) that it will automatically unschedule any selector it has. Is there any need to unschedule a selector when you are going to replace the scene?
I'm using cocos2d-iphone 1.0.1.
Just have a look at replaceScene: implementation in CCDirector.m.
You will see it does not do very much: it simply removes your CCScene from an array and replaces it with the new one.
This, if everything works correctly, will make your scene to be deallocated. This will call dealloc both in CCScene and CCNode (CCScene base class). You can also check the implementation and see that those methods do not do anything with scheduled methods.
So, it is up to your CCScene class to do any required cleanup in dealloc (or onExit, whatever makes sense to you).
Related
Is there a standard way to change between scenes in Minko? Specifically, I'm imagining each scene as a different level, and when the user completes some task the entire level changes.
I know I could just update all my meshes and whatnot but this feels poor; is there a way I can build a root node for a new scene and then switch the Canvas to using that root node instead (as well as force a rererender, since all the objects will have changed)?
Your second idea is fine. You can create a separate root Node with its own SceneManager sharing the Canvas. Add your new scene to this Node. When you're ready to switch, change the SceneManager you use in the enterFrame signal to render. This should trigger a re-render, upload textures, calls component added signals...
In Minko, there is no global singleton or anything that would prevent from having to completely separate scenes. Each SceneManager will reference its own AssetLibrary. This way, if you switch scenes and remove references to the previous SceneManager, the assets will be released from memory.
Thanx in advance..I have a problem , how we release memory in cocos2dx ??
In my game, my first scene takes a lot of memory because there are so many animations run at a single time on this scene,there are so many animations , so i am satisfied with this but when we go to next scene, it does not release previous memory used,this is my problem so how we release memory used by previous scene when we change the scene?
To go between scenes you can either call pushScene or replaceScene.
Push Scene
If you're pushing between scenes then I recommend that you have a loading scene in between. It should be lightweight so that you have a chance to release everything from your old scene. This is where the onEnter(DidFinish) and onExit(DidStart) methods come in handy.
The chain of calls would be:
oldScene->onExitDidStart()
loadScene->onEnter()
oldScene->onExit() <-- this is where you release everything
loadScene->onEnterDidFinish() <-- this is where you load up the new scene
newScene->onEnter()
and so on... If you've managed your memory correctly then you shouldn't have 2 heavy scenes at once.
Replace Scene
This is a much easier scenario. You simply need to make sure that for the new scene you load as little as possible until the old scene has completely disappeared. I.e. when onEnterDidFinish() is called, or even 1 frame after it.
Cocos2d-x supports auto release memory. For example, when you create a sprite by calling Sprite::create() it will add this sprite to the auto-release pool. If you don't add this sprite to become the child (or n-th leveled child) of the current scene, it will be released.
Do not create an object using new,use create() instead when you call the next scene, everything from the last scene are released.
can anyone please make me clear about the difference between a Scene & a Layer in COCOS2D. I am bugged up with this.
Buddy, it is very simple. Whenever you use COCOS2D, you will be having a class which extends Layer. And which you are going call from Main activity. So for one displayable screen, there can be only one layer. In the class(which extends Layer) can have any number of scenes. You can even set the dimensions for the individual scenes too. But, make sure that, you release the memory immediately after you switch from one scene to another... Enjoy... :)
I have a CCSprite that I'm using in a scene and have created multiple CCAnimation actions to apply to it all using a single CCSpriteFrameCache sharedSpriteFrameCache. While everything is working and I'm able to switch between animations, I feel like I'm doing poorly and would like to simplify my code by retrieving the running action(s) on the CCSprite to stop them individually before running the next action on it.
To help create some context, lets assume the following situation:
We have a CCSprite called mySprite
We have 3 separate CCAnimation actions defined for walking to the right, walking to the left, and sitting looking forward called: actionAnimWalkRight, actionAnimWalkLeft, and actionAnimSitForward respectively.
We want to have the sprite walk to the right when someone touches the screen right of mySprite, walk left when someone touches the screen left of mySprite and sit when someone touches mySprite.
The approach I'm using to accomplish this is as follows:
Place CCSprite as a child in the scene.
Tell the sprite to run an action using: [self runAction:actionWalkRight];
When I want to change the action after someone touches, I have a method called stopAllAnimationActions which I call before I apply a new action that stops any animation action no matter what's running. Basically lists ALL the CCAnimation/CCActions I have defined and stops each one individually since I don't want to use stopAllActions. as follows: [self stopAction:actionWalkRight]; [self stopAction:actionWalkLeft]; [self stopAction:actionSitForward];
Then I apply the new animation after the above method fires using: [self runAction:actionWalkLeft];
While this works, it just seems like a poor design to stop items that I know aren't running just because I don't know exactly what is running. So just looking for advice and the best recommended practice to do something like this within very complex situations so tracking every possible situation is difficult. Any feedback would be appreciated.
When creating the actions set the tag of that action with a constant:
actionWalkRight.tag= kCurrentAction;
[self runAction:actionWalkRight];
Then, retrieve the running action by that tag and stop it.
[self stopActionByTag:kCurrentAction];
I recommend you simplify your process and take advantage of the native Cocos features, including stopAllActions. Don't re-use actions, always create them from scratch as it has been well discussed among Cocos developers that re-using actions can be buggy.
Cocos is well optimized and features like stopAllActions are not performance hogs. It would probably be faster than your approach, actually.
What is the role of the scene in Cocos2d?
The scene instantiates layers, like for instance a GameEngineLayer, a HUDLayer, etc.
I guess the GameEngineLayer class can be identical between scenes, but there will of cause be different objects in different scenes.
In scene1 there may be one Santa, and one Rudolf, whereas in scene2 there are just two Santa. Shall scene1 instantiate a santa, and one rudolf and pass them in a list of game objects to its instance of the gameEngine? And scene two instantiate two santa following the same pattern?
Shall the scenes also pass a list of events down to their respective gameEngine instance with time stamped events? For instance that santa shall feed Rudolf after a one minute?
Is the responsibility of the scene to do these kind of things?
I've started with a cocos2d/box2d game one week ago, so I'm a beginner. I've read lots of examples, but they usually code everything in a HelloWorldLayer class. :)
Added example:
http://www.raywenderlich.com/4666/how-to-create-a-hud-layer-with-cocos2d
The scene is defined inside ActionLayer.mm. Why?? Why not have Scene1.m that instantiates the ActionLayer?
The only reason why there's a CCScene in cocos2d is because CCDirector requires it as the base class for methods like runWithScene and replaceScene. Other than that, CCScene, CCLayer and CCNode are virtually identical to each other.
You can give scenes, layers, nodes, sprites, etc. any role you want.
But typically the Scene assumes the role of the state manager of the currently active game objects (nodes). A common use case is to declare the scene a singleton so that any child node can access the scene's base methods, for example to send other unrelated nodes messages, or to check if the game is over, and so on.
For propagating events I'm in favor of passing events down, since there's no easy way to pass events up as there is in UIKit. However it depends on what kind of events and what type of design you prefer.
Whether Santa sends a message to Rudolf in order to feed it, or Rudolf frequently asking Santa whether it is has something to eat, is also up to you. There are pros and cons to both approaches.
The reason why many examples instantiate the CCScene object inside the CCLayer class is simply because of that requirement of Cocos2D having to have a scene. Personally I think it's a bad case of a bad example that has become a de facto standard over the years. It would have been better to always create a CCScene class, and inside that create all the layers and other nodes that you want. It would have made the relation between scenes and layers and other nodes more obvious. As it is, there's many many projects out there whose scene class simply does nothing but contain a single layer that runs all the code.