Cocos2d-x HTML v2.1: How to migrate from v2.0
I've been getting to know cocos2d-x HTML5 edition for the last few weeks as I try to port one of my mobile applications to HTML5/JS (Pocket Bombs). So far I have had a positive experience with the HTML5 port of the framework (Barring the usual JavaScript annoyances, of course).
A new version of the framework was released a couple days ago (v2.1). This new edition does NOT preserve the same API as the previous version (v2.0). This article explains what I had to do to get my v2 project working with the v2.1 framework.
References:
- cocos2d-x v2.1 announcement [cocos2d-x.org] (HTML5 download link is further down on the page)
- HelloHTML5World Sample Project [Found in the ZIP file that contains v2.1 of cocos2d-x html5]
- samples/tests/index.html sample project [Found in the ZIP file that contains v2.1 of cocos2d-x html5]
Overview of changes
Before we get into the details, here's a high-level summary of what files will need to be changed in your project to migrate from v2.0 to v2.1 of cocos2d-x html5:
- cocos2d.js
- main.js
- Any UI Code that uses toggle buttons
Changes to cocos2d.js
The cocos2d.js file lives in the same folder as your main index.html file. Here are the changes that I had to make to get this file to work.
Change 1
Change var c to include a couple new items (This is the configuration cocos2d-x uses). New items are bolded
From:
var c = {
COCOS2D_DEBUG:2, //0 to turn debug off, 1 for basic debug, and 2 for full debug
box2d:false,
showFPS:true,
frameRate:60,
tag:'gameCanvas', //the dom element to run cocos2d on
//engineDir:'../cocos2d/',
engineDir: '../Cocos2d-html5-v2.0/cocos2d/',
appFiles:['Classes/PB.Initialize.js', 'UI/Game/PB.UI.Game.Default.js']
};
To:
var c = {
COCOS2D_DEBUG:2, //0 to turn debug off, 1 for basic debug, and 2 for full debug
box2d:false,
chipmunk:false,
loadExtension:false,
showFPS:true,
frameRate:60,
tag:'gameCanvas', //the dom element to run cocos2d on
//engineDir:'../cocos2d/',
engineDir: '../Cocos2d-html5-v2.1/cocos2d/',
appFiles:['Classes/PB.Initialize.js', 'UI/Game/PB.UI.Game.Default.js']
};
Change 2
Replace the window.addEventListener('DOMContentLoaded', function () with the new one provided in the HelloHTML5World sample
From:
window.addEventListener('DOMContentLoaded', function () {
//first load engine file if specified
var s = d.createElement('script');
s.src = c.engineDir + 'platform/jsloader.js';
d.body.appendChild(s);
s.c = c;
s.id = 'cocos2d-html5';
});
To:
window.addEventListener('DOMContentLoaded', function () {
//first load engine file if specified
var s = d.createElement('script');
/*********Delete this section if you have packed all files into one*******/
if (c.SingleEngineFile && !c.engineDir) {
s.src = c.SingleEngineFile;
}
else if (c.engineDir && !c.SingleEngineFile) {
s.src = c.engineDir + 'platform/jsloader.js';
}
else {
alert('You must specify either the single engine file OR the engine directory in "cocos2d.js"');
}
/*********Delete this section if you have packed all files into one*******/
//s.src = 'Packed_Release_File.js'; //IMPORTANT: Un-comment this line if you have packed all files into one
document.ccConfig = c;
s.id = 'cocos2d-html5';
d.body.appendChild(s);
//else if single file specified, load singlefile
});
Changes to main.js
The main.js file lives in the same folder as your index.html file. Here are the changes that I had to make to get this file to work. I've highlighted the changes below in bold to make it easier to see what needs to be changed.
In a Nutshell, cc.Loader.shareLoader() changed to cc.Loader.getInstance() and cc.LoaderScene.shareLoaderScene() changed to cc.LoaderScene.getInstance()
From:
var cocos2dApp = cc.Application.extend({
config:document.querySelector('#cocos2d-html5')['c'],
ctor:function (scene) { // Accepts a Scene for runnning
this._super();
this.startScene = scene;
cc.COCOS2D_DEBUG = this.config['COCOS2D_DEBUG'];
cc.setup(this.config['tag']);
cc.Loader.shareLoader().onloading = function () {
cc.LoaderScene.shareLoaderScene().draw();
};
cc.Loader.shareLoader().onload = function () {
cc.AppController.shareAppController().didFinishLaunchingWithOptions();
};
cc.Loader.shareLoader().preload([
{type:"plist",src:"Themes/spritesheet1.plist"},
{type:"plist",src:"Themes/spritesheet2.plist"}
]);
},
applicationDidFinishLaunching:function () { // This function launches your code
var director = cc.Director.getInstance();
director.setDisplayStats(this.config['showFPS']);
director.setAnimationInterval(1.0 / this.config['frameRate']);
director.runWithScene(new this.startScene());
return true;
}
});
To:
var cocos2dApp = cc.Application.extend({
config:document['ccConfig'],
ctor:function (scene) { // Accepts a Scene for runnning
this._super();
this.startScene = scene;
cc.COCOS2D_DEBUG = this.config['COCOS2D_DEBUG'];
cc.initDebugSetting();
cc.setup(this.config['tag']);
cc.Loader.getInstance().onloading = function () {
cc.LoaderScene.getInstance().draw();
};
cc.Loader.getInstance().onload = function () {
cc.AppController.shareAppController().didFinishLaunchingWithOptions();
};
cc.Loader.getInstance().preload([
{type:"plist",src:"Themes/spritesheet1.plist"},
{type:"plist",src:"Themes/spritesheet2.plist"}
]);
},
applicationDidFinishLaunching:function () { // This function launches your code
var director = cc.Director.getInstance();
director.setDisplayStats(this.config['showFPS']);
director.setAnimationInterval(1.0 / this.config['frameRate']);
director.runWithScene(new this.startScene());
return true;
}
});
Changes to Your UI Code
This is the fun part. Now that your program can get to the point of loading in a web browser you'll probably see a bunch of errors like Assertion failed: child already added. It can't be added again or something like that.
I found a couple of APIs had changed for the Menu system and I had to change all instances of my old usage to the new system. The specific APIs that have changed (that I have been able to identify) are:
- cc.MenuItemFont.create
- cc.MenuItemToggle.create
Change to cc.MenuItemFont.create
For Clarity I have bolded the changes in the v2.1 API.
Before (v2.0):
var newGameBtn = new cc.MenuItemFont.create("New Game", this, this.newGame);
Now (v2.1):
var newGameBtn = cc.MenuItemFont.create("New Game", this.newGame, this);
Comments:
This change involved flipping the last 2 arguments of the create API to include the callback function first
Change to cc.MenuItemToggle.create
For Clarity I have bolded the changes in the v2.1 API.
Before (v2.0):
var bToggle = cc.MenuItemToggle.create(this,this.toggle, cc.MenuItemFont.create("4"), cc.MenuItemFont.create("5"));
Now (v2.1):
var bToggle = cc.MenuItemToggle.create(cc.MenuItemFont.create("4"), cc.MenuItemFont.create("5"));
bToggle.setCallback(this.toggleBoardSizeX, this);
Comments:
With this one we now have to add the callback information in a new API call setCallback().
Final Thoughts
While the changes between v2.0 and 2.1 are fairly small, it is a hassle to have to go back through all your API calls to match the new syntax. Hopefully cocos2d-x html5 will continue to stabilize its API over time. I wasn't expecting any changes in a point release! :)
With that said, I think the guys who maintain cocos2d-x have done a great job. The framework is solid and is meeting my needs. Thanks!