Wednesday, November 6, 2013

Hosting a Static Website on AWS S3

Step by step guide provided by AWS here: http://docs.aws.amazon.com/AmazonS3/latest/dev/website-hosting-custom-domain-walkthrough.html

MongoDB vs MongoLab for Early Stage Live Apps

MongoDB and MongoLab are the 2 main MongoDB hosted service providers who provide their servers within the AWS network and in all regions. For a startup just going live with a new product, volume is initially expected to be low but HA may also be a requirement. Obviously cost is also an issue.

With these in mind the shared instances sound like the way to go, unfortunately with MongoLab this option is not available in all AWS regions. It also comes at a big jump in price from the single server shared plan (i.e. $15 -> $89 for same storage). Bump up the budget to $200 a month and you can get a dedicated instance with much more storage and dedicated RAM. With MongoHQ it gets worse with no cluster / replica-set options available.

So moving on to dedicated instances, MongoLab provides cluster / replica-set options for as little as $200 a month, while MongoHQ doesn't do so until you reach the $1345 a month price plan. For a startup just starting out trying to save costs and not wanting to compromise on HA, seems like MongoLab is the obvious choice purely basing on the packages and price plans.

References:

DynamoDB Hash and Range

Hash doesn't have to be unique if "Hash and Range" PK is selected. In this case, it is used for evenly sharding the data under-the-hood.

However, the Hash and Range combination should be unique (not mentioned specifically but obvious and implied).

More details in the following references:

Handling Complex Objects in DynamoDB

Apparently AWS's Java APIs provide means to handle this.

Link: https://java.awsblog.com/post/Tx1K7U34AOZBLJ2/Using-Custom-Marshallers-to-Store-Complex-Objects-in-Amazon-DynamoDB

Articles With Comparison Between DynamoDB and MongoDB (Part 2)


Tuesday, November 5, 2013

Cocos2D-X: Drawing Rectangle with Border

This needs to be done in 2 draws, one to draw the border and the other to draw a solid rectangle.

Example code:

void MyLayer::draw()
{
CCPoint p1 = ccp(x1,y1);
CCPoint p2 = ccp(x2,y2);

   ccColor4F color;
   color.a = 1.0;
   color.r = 0;
   color.g = 0;
   color.b = 0;
   ccDrawSolidRect(p1,p2, color);
   
   ccDrawColor4B(255, 255, 255, 255);
   ccDrawRect(p1,p2);
}

p1 being the bottom left corner of the rectangle and p2 being the top right.

In order for this to be called, the function needs to be override the "draw" function of the parent.

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