Santa Clara Games

dic 10, 2013

Pixel Perfect using Cocos2D-HTML5

As soon as we started developing "Hassleheart", we had to make sure we could use pixel-perfect sprites in Cocos2D HTML5 and make it as painless as possible.

The basic pixel-perfect challenge comes with making sure Cocos2d doesn't apply antialias effects to your textures. Thankfully, this can be easily done by invoking the setAliasTexParameters() function after you create a Sprite. A piece of cake, right?

Well, in the end, we didn't like this solution too much, finding it impractical to expect programmers to remember to call this function every time they create a sprite. I know myself enough not to trust me.  Sooner or later, I would forget to do this, and the game would look all fuzzy.

Another solution could be to extend the cc.Sprite initialize method in order to use call the setAliasTexParameters function after the sprite is created. Example:

~~~~ {.prettyprint .lang-js .linenums} var myCCSprite = cc.Sprite.extend({ initWithSpriteFrame: function ( texture ) { this._super(); this.getTexture().setAliasTexParameters(); } });

This way, we extend the original CCSprite class and use only the
myCCSprite class to create our sprites. All done, right?  Well, not
quite. What about other Cocos 2D classes such as cc.SpriteFrameCache or
cc.SpriteBatchNode? They still use the original cc.Sprite class, knowing
nothing about our myCCSprite extension :,(

Another approach could be to patch the CCSprite.js file
directly, modifying its initializer method. But that would be far from
elegant, hardcoding the assumption that all games are to be
pixel-perfect and forcing us to merge this change any time the Cocos2D
team releases a new version.

The last and most optimal approach involved modifying the initializer
function at runtime like this:

~~~~ {.prettyprint .lang-js .linenums}
var __CCSprite_initWithSpriteFrame = cc.Sprite.prototype.initWithSpriteFrame;
cc.Sprite.prototype.initWithSpriteFrame = function() {
  var ret = __CCSprite_initWithSpriteFrame.apply(this, arguments);

  if ( ret ) {
    this.getTexture().setAliasTexParameters();
  }

  return ret;
};

By extending the original instance method and building on its prototype, we are able to achieve the most elegant solution because we avoid modifying the original implementation.  Now, if Cocos2D changes its implementation, our code will still support it, while at the same time, we ensure that any Cocos2D class that uses cc.Sprite class will be passing through our extended prototyping of the initWithSpriteFrame method.

dic 09, 2013

Export Pixel Perfect Graphics from Illustrator

It's quite difficult unless you have all the following steps in mind:

  1. When you create a new document in Illustrator, set the resolution to 72 dpi in RGB mode.  This helps later to avoid unexpected results when exporting your graphics.

    illustrator-new-document

  2. Once you've got your document open, go to the VIEW menu > PIXEL PREVIEW.  That way, when you zoom in or out, you'll be able to see the grid in pixels.

  3. Finally, to top it all off, you can make sure everything comes out pixel-perfect by going to the TRANSFORMATION menu. Once you see the following dialog box:

    alignCheck the ALIGN TO GRID option, and everything will adjust itself quite nicely.

And that's it!  Later, when you export, it's best to use PNG without anti-aliasing in order to avoid the blur effect that comes with JPEG compressions.