Cocos2D for the Web

Upgrading from v0.1 to v0.2

To upgrade your project from v0.1 to v0.2 you should first start by creating a new v0.2 project and then replace the src folder with the one from your v0.1 project.

Next create a file called src/config.js and add this line to it.

exports.ENABLE_DEPRECATED_METHODS = true

What this config option does is enable the use of deprecated methods and objects. This should be enough to make an existing project functional, but in the long term you should not keep this option enabled and instead remove all calls to the deprecated methods. The rest of this guide will explain what these are.

Coordinate Origin

The make Cocos2D JavaScript behave more like other versions of Cocos2D I’ve flipped the Y axis. This means that point 0×0 is in the bottom left corner rather than the top left. If you don’t like his behaviour you can swap back to top-left origin by adding this line to your src/config.js file. However I would recommend keeping bottom left as your origin if you can.

exports.FLIP_Y_AXIS = false

Deprecated Features

No built in objects inherit from the now deprecated BObject class. The majority of deprecated methods came from this class and have been replaced with standard JavaScript. The goal was to make Cocos2D JavaScript more like normal JavaScript code without the need for too many helper functions, although there are a few optional ones to make life easier.

Requiring Modules

In v0.1 it was possible to require your own modules without prefixing them with a slash. This doesn’t happen in v0.2. e.g. If you have a file: foo/bar/baz.js you used to require it with: require('foo/bar/baz'), but now this is reserved for loading libs and built in modules. Instead, in v0.2 you have to use an absolute path require('/foo/bar/baz') or a relative path require('./foo/bar/baz').

If you don’t like this behaviour then simply add this line to the very top of your main.js

require.paths.unshift('/')

The paths array is a list of paths that require will search for modules if you the module path is not prefixed with ‘./’ or ‘/’.

Initialisation

Because assets (images, tilemaps, etc) are no longer embedded inside the JavaScript file itself, they now need to be pre-loaded. This task is performed by the Director and if you create a new project you will see all the code involved in doing this. But if you’re upgrading you will need to swap out the old initialisation code for the new. This is the new code.

exports.main = function () {
    // Initialise application

    // Get director singleton
    var director = cocos.Director.sharedDirector

    // Wait for the director to finish preloading our assets
    events.addListener(director, 'ready', function (director) {
        // Create a scene and layer
        var scene = new cocos.nodes.Scene()
          , layer = new MyGame()

        // Add our layer to the scene
        scene.addChild(layer)

        // Run the scene
        director.replaceScene(scene)
    })

    // Preload our assets
    director.runPreloadScene()
}

Accessors

Both the get and set methods have been removed. Instead you use normal JavaScript properties in the usual way.

In v0.1

this.set('isMouseEnabled', true)
var s = cocos.Director.get('sharedDirector').get('winSize')
sprite.set('position', new Point(s.width / 2, s.height / 2))

In v0.2

this.isMouseEnabled = true
var s = cocos.Director.sharedDirector.winSize
sprite.position = new Point(s.width / 2, s.height / 2)

Because of this change you have to define custom setters and getters using ECMAScript 5 syntax rather than using the get_ or set_ prefix on a function.

In v0.1

{
    get_fooBar: function() { return this._foobar },
    set_fooBar: function(x) { this._foobar = x }
}

In v0.2

{
    get fooBar () { return this._foobar },
    set fooBar (x) { this._foobar = x }
}

For more information on accessors in JavaScript take a look at Defining getters and setters on the MDN.

Inheritance

Inheritance is done in a more traditional JavaScript style. Instead of using extend you will assign an instance of the parent object’s prototype the prototype of your new object.

In v0.1

var Foo = Bar.extend({
    init: function () {
        // Foo constructor
    }
})

In v0.2

function Foo() {
    // Foo constructor
}
Foo.prototype = Object.create(Bar.prototype)
Inherit helper

Optionally, you can use the helper method inherit which has been added to the global Function prototype.

function Foo() {}
Foo.inherit(Bar)

This helper also lets you pass in an additional object which contains the extra properties you wish to add to the new object.

function Foo() {
    // Foo constructor
}

Foo.inherit(Bar, {
    baz: 'xyz',

    buh: function (a, b, c) {
    }
})
Calling ‘super’

To make calling the ‘super’ of a function easier there is a helper property called superclass which points to the parent object’s prototype.

function Foo() {
    // Foo constructor
    Foo.superclass.constructor.call(this)
}

Foo.inherit(Bar, {
    baz: 'xyz',

    buh: function (a, b, c) {
        Foo.superclass.buh.apply(this, arguments)
    }
})

Instantiating

Previously to create instances of an object you would call the static method create on the constructor. Now you simply use the new keyword as you would do normally.

In v0.1

var x = Foo.create('bar')

In v0.2

var x = new Foo('bar')

Callbacks

Version 0.1 provided a utility function for creating callbacks. This has be deprecated in favour of using Function#bind.

In v0.1

var callback = util.callback(this, 'myCallback')

In v0.2

var callback = this.myCallback.bind(this)

Complete Example

Here is a more complete example showing a class in v0.1 and the same class in v0.2.

v0.1
var SpriteDemo = nodes.Layer.extend({
    _title: 'No title',
    subtitle: null,

    init: function () {
        SpriteDemo.superclass.init.call(this)

        var s = cocos.Director.get('sharedDirector').get('winSize')

        var label = nodes.Label.create({ string: this.get('title'), fontName: 'Arial', fontSize: 26 })
        this.addChild({ child: label, z: 1 })
        label.set('position', new Point(s.width / 2, s.height - 50))


        var subtitle = this.get('subtitle')
        if (subtitle) {
            var l = nodes.Label.create({ string: subtitle, fontName: "Thonburi", fontSize: 16 })
            this.addChild({ child: l, z: 1 })
            l.set('position', new Point(s.width / 2, s.height - 80))
        }


        var item1 = nodes.MenuItemImage.create({ normalImage: path.join(__dirname, "/resources/b1.png"),
                                               selectedImage: path.join(__dirname, "/resources/b2.png"),
                                                    callback: util.callback(this, 'backCallback') })

        var item2 = nodes.MenuItemImage.create({ normalImage: path.join(__dirname, "/resources/r1.png"),
                                               selectedImage: path.join(__dirname, "/resources/r2.png"),
                                                    callback: util.callback(this, 'restartCallback') })

        var item3 = nodes.MenuItemImage.create({ normalImage: path.join(__dirname, "/resources/f1.png"),
                                               selectedImage: path.join(__dirname, "/resources/f2.png"),
                                                    callback: util.callback(this, 'nextCallback') })

        var menu = nodes.Menu.create({ items: [item1, item2, item3] })

        menu.set('position',  new Point(0, 0))
        item1.set('position', new Point(s.width / 2 - 100, 30))
        item2.set('position', new Point(s.width / 2, 30))
        item3.set('position', new Point(s.width / 2 + 100, 30))
        this.addChild({ child: menu, z: 1 })
    },


    get_title: function () {
        return this._title
    },

    set_title: function (newTitle) {
        this._title = newTitle
    },

    restartCallback: function () {
        var director = cocos.Director.get('sharedDirector')

        var scene = nodes.Scene.create()
        var action = restartAction()
        scene.addChild({ child: action.create() })

        director.replaceScene(scene)
    },

    backCallback: function () {
        var director = cocos.Director.get('sharedDirector')

        var scene = nodes.Scene.create()
        var action = backAction()
        scene.addChild({ child: action.create() })

        director.replaceScene(scene)
    },

    nextCallback: function () {
        var director = cocos.Director.get('sharedDirector')

        var scene = nodes.Scene.create()
        var action = nextAction()
        scene.addChild({ child: action.create() })

        director.replaceScene(scene)
    }
})

var demo = SpriteDemo.create()
v0.2
function SpriteDemo () {
    SpriteDemo.superclass.constructor.call(this)

    var s = cocos.Director.sharedDirector.winSize

    var label = new nodes.Label({string: this.title, fontName: 'Arial', fontSize: 26})
    this.addChild({ child: label, z: 1 })
    label.position = new Point(s.width / 2, s.height - 50)


    var subtitle = this.subtitle
    if (subtitle) {
        var l = new nodes.Label({string: subtitle, fontName: "Thonburi", fontSize: 16})
        this.addChild({ child: l, z: 1 })
        l.position = new Point(s.width / 2, s.height - 80)
    }


    var item1 = new nodes.MenuItemImage({ normalImage: path.join(__dirname, "/resources/b1.png"),
                                        selectedImage: path.join(__dirname, "/resources/b2.png"),
                                             callback: this.backCallback.bind(this) })

    var item2 = new nodes.MenuItemImage({ normalImage: path.join(__dirname, "/resources/r1.png"),
                                        selectedImage: path.join(__dirname, "/resources/r2.png"),
                                             callback: this.restartCallback.bind(this) })

    var item3 = new nodes.MenuItemImage({ normalImage: path.join(__dirname, "/resources/f1.png"),
                                        selectedImage: path.join(__dirname, "/resources/f2.png"),
                                             callback: this.nextCallback.bind(this) })

    var menu = new nodes.Menu({ items: [item1, item2, item3] })

    menu.position  = new Point(0, 0)
    item1.position = new Point(s.width / 2 - 100, 30)
    item2.position = new Point(s.width / 2, 30)
    item3.position = new Point(s.width / 2 + 100, 30)
    this.addChild({ child: menu, z: 1 })
}

SpriteDemo.inherit(nodes.Layer, {
    _title: 'No title',
    subtitle: null,

    get title () {
        return this._title
    },

    set title (newTitle) {
        this._title = newTitle
    },

    restartCallback: function () {
        var director = cocos.Director.sharedDirector

        var scene = new nodes.Scene()
        var action = restartAction()
        scene.addChild({ child: new action() })

        director.replaceScene(scene)
    },

    backCallback: function () {
        var director = cocos.Director.sharedDirector

        var scene = new nodes.Scene()
        var action = backAction()
        scene.addChild({ child: new action() })

        director.replaceScene(scene)
    },

    nextCallback: function () {
        var director = cocos.Director.sharedDirector

        var scene = new nodes.Scene()
        var action = nextAction()
        scene.addChild({ child: new action() })

        director.replaceScene(scene)
    }
})

var demo = new SpriteDemo()

Posted

Add Comment

If you want to add a comment, then simply fill in the form below. All fields are required.