Friday, July 17, 2015

A Tale Of Two Constructors

Or - Integrating cocos2d-js inheritance with native coffeescript classes. Nah, that just sounds boring.

Here is the thing. Many existing script modules use a simple inheritance model much like the one described by John Resig. That being the case, I can simply extend framework classes using coffeescript's extend keyword:

class Game extends Phaser.State

class Scores extends Backbone.Model

This works because coffeescript uses the same basic model. But try that with cocos2s-js:

class Game extends cc.Layer

Sure, it will compile. But when I run the app, I just see a black screen, and there are no errors showing up in the console. This is because Cocos-js uses a different inheritance model, with it's own constructor and super methods. Instead of extending your object with a superclass, cocos requires you to pass in a prototype object that is used as a mixin to dynamically build a new class:

klass = cc.Layer.extend(Game::)

You can also use a new Game object instead of the prototype. I use a factory method:

class Game
  @create:() -> new (cc.Layer.extend(new Game()))

and then I have to do is remember to call Game.create() instead of new Game()

So where are the 2 constructors? You said there would be 2 constructors.

Suppose we have this class to define the main menu:

class Menu

  @create: (args...) => new (cc.Layer.extend(new @(args...)))

  user: ''
  debug: false

  constructor: (options) ->
    @user = options.user
    @debug = options.debug

  ctor: ->
    @_super()
    quitNormal = new cc.Sprite(res.quit_png, cc.rect(0, 0, 64, 64))
    quitSelected = new cc.Sprite(res.quit_png, cc.rect(64, 0, 64, 64))
    quitDisabled = new cc.Sprite(res.quit_png, cc.rect(128, 0, 64, 64))
    quit = new cc.MenuItemSprite(quitNormal, quitSelected, quitDisabled, @onQuit)
    quitMenu = new cc.Menu(quit)
    {width, height} = cc.director.getWinSize()
    backMenu.setPosition(cc.p(width - 40, height - 10))
    @addChild(backMenu)
    true

  onQuit: =>
    cc.log 'Bye'


Then we invoke it in a scene.

  scene = new cc.Scene()
  scene.addChild(Menu.create(debug:true, user:'Norville Rogers'))
  cc.director.runScene(scene)


  • The first, native constructor is called by new @(args...). 
  • The second constructor, 'ctor' gets called later by new (cc.Layer.extend())


cc.log('Name:', level.name)

Prints to the console:

 Name: Norville Rogers

Tuesday, July 14, 2015

Visual Studio Code for Linux

Code: A Visual Studio for Linux.  Now I understand how Alice must have felt in Wonderland.

Code is a preview with only 2 releases under it's belt. And it's quickly becoming my favorite javascript editor. It's blazingly fast. I hate slow code editors. And it has Intellisense! The biggest thing missing is a quick way to preview my web page. But I can work around that:
  1. $ cd MyProject
  2. $ npm install --save-dev superstatic
  3. $ npm install --save-dev open
  4. Edit the file .settings/launch.json. If this file doesn't exist, hit F5, and a new template will be created.
  5. Change "program": "main.js" to "program": "bin/server.js",
  6. Then create bin folder and the file bin/server.js (code below)
Now, when you hit the F5 key, you can preview your web page in your default browser. This works for me on both Linux Mint and Windows 7.

Assuming that my project has a web/index.html as the main page:

/**
 * Run a static server
 */
var server = require('superstatic').server;
var open = require('open');
var path = require('path');

var options = {
 port: 3474,
 host: 'localhost',
 config: {
  root: './web',
  routes: {
   '/': 'index.html'
  }
 },
 cwd: path.resolve(__dirname, '..'),
 debug: false 
};

server(options).listen(function(err) {
 open('http://localhost:3474');
});