Sunday, July 21, 2013

Cocos2D-X for Android LiveWallpaper

Today i saw a question on the forum at asking about how to get the cocos2d-x application to run as a live wallpaper.

Most of the basics come from the sample application provided by google, but since cocos2d-x is designed under the assumption that its' always used as an application you will have to change a few things here and there.

So ive' quickly made some dirty adjustments to the code pasted on the forum to get the sample code running as a live wallpaper. Here is the screenshot of the default one running.
Sample Cocos2D-x app as Live Wallpaper
Im' excited to see what the cocos2d-x app devs can do once they start developing the live wallpapers. ..

Here are the steps you should follow:

1) Open the .java file created in packagename/*.java
2) Modify it based on the java file embedded below.
3) Modify the AndroidManifest.xml file to make it behave like a wallpaper.

Build and deploy the app just like any other cocos2d-x application. If everything went right you should see your app listed among the liveWallpapers section in your phone.

AndroidManifest.xml has to be modified. Then the code in your java file should be changed to this.

Cocos2D-X Memory Management

The last couple of days i have been trying to squash all the memory leaks in our game, this gave me a better understanding about the memory management used by cocos2d-x. It's a little different but with a little care you can get it right.

Here are a few facts you should know

  •  Every CCObject has a reference count of 1 when it is created.
  •  If you call autorelease() and dont' retain the CCObject you don't have to call release()
  •  CCNode's destructor calls release() on all its' children once(because it calls retain() in addChild())
  •  If you call retain() or new on a CCObject you have to call release() 

This is all straight forward, in fact this is all mentioned in the wiki on website.
It gets' tricky when you start using CCTouchDispatcher's targeted delegate and the CCBReader.

When you load a ".ccbi" file the following happens:

  • CCBAnimationManager calls retain() on RootNode of the "ccb"
  • RootNode of the "ccb" calls retain() on CCBAnimationManager (it is set as userObject()).

so if the RootNode has to be deleted, CCBAnimationManager has to call release() on RootNode, but the CCBAnimationManager will be deleted only when RootNode calls release() on CCBAnimationManager. This is the cyclic dependency because of which both the RootNode and the AnimationManager stay in memory.

To counter this we have to create a wrapper class which keeps track of the CCBAnimationManager. Set the userObject in RootNode to NULL so that the CCBAnimationManager is no longer dependent on RootNodes's deletion. Check out the following link for full discussion.

The other most important thing is that, when you use CCB_MEMBERVARIABLEASSIGNER_GLUE(...) for accessing the children in the "ccb" files, it calls retain() on the member you get access to. So it's crucial to call release() on it in the destructor().