Thursday, October 31, 2013

Cocos2D-X: Useful Code Saving Memory Management Macros


CC_SAFE_RELEASE: Checks whether the object is valid before calling "release" on it.

CC_SAFE_RELEASE_NULL: Checks whether the object is valid before calling "release" on it, and then also sets the variable to NULL.

CC_SAFE_RETAIN: Use when it's possible that the return value from a function can be NULL and you don't want to call retain on a NULL value.


#define CC_SAFE_RELEASE(p)            do { if(p) { (p)->release(); } } while(0)
#define CC_SAFE_RELEASE_NULL(p)        do { if(p) { (p)->release(); (p) = 0; } } while(0)
#define CC_SAFE_RETAIN(p) do { if(p) { (p)->retain(); } } while(0)

Wednesday, October 30, 2013

iOS Autorelease After Creating New Object

It is recommended to call "autorelease" after create a new object via the "new" operator (or any other method that leaves the retain count set at 1 but doesn't call "autorelease"). This is because after a "new" operator, the retain count of the object is set to "1" to ensure that it doesn't get destroyed. If "autorelease" is not called, the object will continue to take up memory until "release" is called on the object. Calling "autorelease" will ensure that the object's retain count is set to reduced by one (important!) after the current event loop is completed and the autorelease pool is drained. This means that if "retain" is called subsequently, the object will still not be destroyed if that is not matched with a corresponding "release".

Note: I ran my tests on Cocos2D-X's implementation of the autorelease pool system but as I understand, it behaves the same as the iOS one.

References:

Cocos2D Cropping Sprites

Useful trick for features like graphical health bars etc.


theSprite->setTextureRect(CCRectMake(x,y,w,h));


Reference: http://www.cocos2d-x.org/forums/6/topics/32721

Cocos2D Draw Order

In summary:

  • If within same parent and same Z order, then nodes that are added first will be drawn first, followed by the ones added later in sequence.
  • If within the same parent and different Z order, then it's according to Z order. The higher the Z order, the later it will be drawn. Note: negative Z order will be drawn before the parent, and positive Z order will be drawn after the parent.
  • If different parents, then the Z order of the parent decides first, then Z order within each parent.
  • The only way for nodes with different parents to be ordered with each other independently of parent is using VertexZ. (However, I could not get it to work with Cocos2D-X Isometric tile maps across map layers. I ended up removing all the objects (e.g. buildings) on the other layers in runtime and re-inserting them in the same layer as the other sprites as sprites, and then ordering via Z order.

C++ Static Variables

Other than the usual differences in scope, there are some unique aspects of the syntax that will stump a developer from a Java background.

While instance variables only require declaration in the header file, a static variable in C++ needs to be declared twice, once in the header file and another in the CPP file. Otherwise you'll get a linker error.

See here for example: http://stackoverflow.com/questions/9282354/static-variable-link-error

Wednesday, October 23, 2013

Cocos2D-X: Tile Map Layer Empty Gotcha

With Cocos2D-X, if you leave a layer with no tiles, there will be a crash that look like this:


bool CCTexture2D::hasPremultipliedAlpha()
{
   return m_bHasPremultipliedAlpha; <-------- EXC_BAD_ACCESS HERE
}

This is due to the CCTexture2D object being undefined when initialising the layer. This can occur when the layer does not have a tile defined.

It is sometimes necessary to have a layer with no tiles defined initially and then define them in code during runtime. However, due to this crash, it is necessary to define those tiles and remove them in code prior to the game starting. Same problem might happen in Cocos2D also.

Tuesday, October 22, 2013

Cocos2D: Checking if Animation Currently Running

Check that "bear->numberOfRunningActions()" returns 0.

Reference: http://stackoverflow.com/questions/12582481/check-if-animation-is-running-in-cocos2d-x

Cocos2D Sprite Sheets: To Use CCSpriteBatchNode Or Not

Examples such as the one here use CCSpriteBatchNode as it is apparently some form of "best practice" to do so due to apparent performance benefits by batching draw operations.

However, the benefits of doing this is debatable, with the following articles claiming only marginal benefits in most use cases, and with significant benefits only in certain situations:

Obviously if using CCSpriteBatchNode is easy then it's a no brainer to use it. But unfortunately it gets pretty complicated when you have a sprite that requires multiple sprite sheets. Rather than to have to figure out how it all has to work, or if it can even work in the first place, it's a pretty straightforward decision instead to not use it.

So from the sprite sheet tutorial, instead of using CCSpriteBatchNode:
  1. Load all the various sprite sheets into the sharedSpriteFrameCache
  2. Create one CCAction for every animation sequence using the frame names
  3. Create a Sprite directly using 1 of the frames
  4. Call runAction on the sprite whenever a new animation sequence needs to be run
Other References:

Thursday, October 17, 2013

Tiled / Cocos2D: Using Objects


  1. Go to Tiled, create an object layer
  2. On the object layer, add objects by using the drawing shapes
  3. If you are using rectangular shapes to represent tiles, you can open the object properties sub-menu after selecting the object and adjust the position and size to fit perfectly the tile
  4. Load the map in Cocos2D and read it with the following code (Example is C++ using Cocos2D-X):

   CCTMXObjectGroup* objectGroup = map->objectGroupNamed(objGroupName);
   CCArray* objects = objectGroup->getObjects();
   
   CCDictionary* objectAsDict;
   CCObject* obj;
   CCARRAY_FOREACH(objects, obj)
   {
       objectAsDict = (CCDictionary*)obj;
       if(!objectAsDict)
       {
           break;
       }
       const char* key = "x";
       int x = ((CCString*)objectAsDict->objectForKey(key))->intValue();
       key = "y";
       int y = ((CCString*)objectAsDict->objectForKey(key))->intValue();
       key = "width";
       int width = ((CCString*)objectAsDict->objectForKey(key))->intValue();
       key = "height";
       int height = ((CCString*)objectAsDict->objectForKey(key))->intValue();


       // figure out which tiles are covered the rectangle here
   }

Note that the coordinates for the rectangle are based on the coordinate system of an ortho tile map (with origin at bottom left). If you are using an iso tile map in Cocos2D, the origin is at the top of the diamond. You'll have to do the necessary conversion.

Cocos2D: Creating a HUD Layer

Here's a guide: http://www.raywenderlich.com/4666/how-to-create-a-hud-layer-with-cocos2d

Cocos2D Sprite Sheets

Guide: http://www.raywenderlich.com/32045/how-to-use-animations-and-sprite-sheets-in-cocos2d-2-x

This is based on sprite sheets generated by Texture Packer, which will also generate plist files for each frame, and also uses offset to minimize white space.

I had to change the following before I could get this to work in Cocos2D-X 2.2.0


   [walkAnimFrames addObject:
       [[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:
           [NSString stringWithFormat:@"bear%d.png",i]]];

Cocos2D-X didn't accept the "CCSpriteFrame" entered here. It was expected "CCAnimationFrame" objects. As such, I had to do this:


CCSpriteFrame* spriteFrame = CCSpriteFrameCache::sharedSpriteFrameCache()->spriteFrameByName(frameName);

CCAnimationFrame* animationFrame = new CCAnimationFrame();
animationFrame->initWithSpriteFrame(spriteFrame, 1.0f, CCDictionary::create());

walkAnimFrames->addObject(animationFrame);

Large Objects in Tiled Map Editor

This article includes a section describing how to include a large object e.g. a large tree or a building in a Tiled map. Basically this involves having a tileset with large tiles and placing them on the map as a separate layer, and then using object layer to specific collision boxes.

Link: http://gamedev.tutsplus.com/tutorials/level-design/introduction-to-tiled-map-editor/

Twitter $10m Pay Cheque, Engineering Talent Wars and the 10x Engineer

Article: http://smallbusiness.yahoo.com/advisor/twitter-pays-engineer-10-million-silicon-valley-tussles-130525209--sector.html

Tuesday, October 8, 2013

Cocos2D-X Multi-Resolution Support

Guide here: http://www.cocos2d-x.org/wiki/Multi_resolution_support

Cocos2D Managing Touch Input

In a subclass of CCLayer, just set "isTouchEnabled" to true and implement the callback functions.

Otherwise, add a touch delegate class to the touch dispatcher. There are 2 types, as explained here: http://www.cocos2d-iphone.org/wiki/doku.php/tips:touchdelegates

Porting From Obj-C to C++ for Cocos2D-X

This page provides a guide for developers when porting code from Obj-C to C++

http://www.cocos2d-x.org/wiki/Moving_From_Objective-C_to_C++

Converting from Screen to Map Coordinates in Isometric 2D Games

This article here provides a great explanation on this.

Formulae in summary:

From screen coordinates to tile x,y

map.x = screen.x / TILE_WIDTH + screen.y / TILE_HEIGHT;
map.y = screen.y / TILE_HEIGHT - screen.x / TILE_WIDTH;


From tile x,y to screen coordinates

screen.x = (map.x - map.y) * TILE_WIDTH_HALF;
screen.y = (map.x + map.y) * TILE_HEIGHT_HALF;



Note: these only work if the iso map is skewed at 45 degrees. If it's skewed in 30 degrees or 60 degrees, trigonometry will be needed.

Thursday, October 3, 2013

Android Google Maps Draw Text Label On Map

Unfortunately, on V2 of the API, this is not possible. The workaround is to create a bitmap image from text, and then draw it as an image Marker.

Solution is described here: http://stackoverflow.com/questions/14631223/draw-text-on-google-map-no-longer-possible

When creating the Paint object, the text size should be calculated during runtime based on the display. This is done according to the example here: http://stackoverflow.com/questions/12620343/text-size-with-different-resolution

Wednesday, October 2, 2013

Git See Older Version of File

Here's a quick way to see the older version of a file in Git:

git show HEAD~4:pathto/file

Where "4" represents the number of versions to go back in HEAD.

See the following references for more details and variations:

Android: ListView Black When Scrolling

Encountered this a couple of times on some Android OS versions.

It's due to the scrolling cache. To fix it, use "setCacheColorHint(preferredBgColor)". I usually just use transparent.

Reference:

Android: Using "ellipsize" to Deal With Long Text

In a TextView the "android:ellipsize" attribute is used to handle rendering of text that is too long for the space given.

More information in the following links: