Hi all,
Thought I would share a few things I have been experiencing in using the CocosBuilderReader with HTML5. I’ve recently been building CocosBuilder projects that have been working with cocos2d-iphone and cocos2d-x. I’ve also recently built a couple games with the HTML5 framework.
First off, I took a look at some of the sample projects … CocosDragonJS and Watermelon with me. What struck me first off the bat was the examples used a different way of defining a class that connects to the cocos builder data. Here is an example of a screen controller with a button connected to a backbutton.
var TestScene = function(){};
TestScene.prototype.onDidLoadFromCCB = function()
{
cc.log("scene loaded");
};
TestScene.prototype.goBack = function()
{
cc.log("goBack");
cc.Director.getInstance().replaceScene(new MyScene());
};
The class is not the CCnode itself but a controller associated with the node. I don’t have a problem with this way of doing things but it is different from the two other languages (obj-c & c**) that cocosbuilder is read into. It also is quite a bit different from the “standard” way to declare classes within the HTML5 cocos library. Fortunately you can define your class in the same way as the cocos libraries and still have it work. The above class can be defined the following way and still gets connected correctly:
<pre>
var TestScene = cc.Layer.extend {
this.*super;
cc.log;
},
goBack:function {
cc.log;
cc.Director.getInstance.replaceScene);
}
});
</pre>
To me, this makes it easier to port from one language to another. I am suspicious that the created object is still not really a full layer class though . This led me to the next experiment.
The next thing that bothered me a bit was the extra flag of being JScontrolled and the extra field this gave to my ccb files. I use cocosbuilder as a common layout, animation, and asset formatter so it seemed wrong to me to have a special flag in there just for JS. I didn’t quite understand why the flag needed to be there. So far … I don’t think it actually does although there are two changes to code I needed to make. You also need to create a loader .
To get my scenes working without the JScontrolled flag I made my class and loader look like this:
<pre>
var TestScene = cc.Layer.extend {
this.*super;
cc.log;
},
onResolveCCBCCMenuItemSelector:function {
if {
return this.goBack;
}
return null;
},
goBack:function {
cc.log;
cc.Director.getInstance.replaceScene);
}
});
var TestSceneLoader = cc.LayerLoader.extend {
cc.log;
return new TestScene;
}
});
TestSceneLoader.loader = function {
return new TestSceneLoader;
};
</pre>
The extra function in TestScene should be familiar to anyone who has used cocosbuilder in cocos2d-x. It is a way to stitch the callbacks. You will need to do this otherwise the CCBReader by default is actually creating a CCNode and not really creating the full TestScene class. There are many different ways this could have been done in CCNodeLoader.js function that would have hidden this away as it is done in the obj-c version. In fact in a code fragment in the library a simpler way is being used when the JScontrolled flag is set .
The TestSceneLoader is again the way that c** dynamically adds classes to be created. The loader code already exists in the JS cocosbuilder code so I used it but again there can be a cleaner way to do this and not require the extra loader code (I won’t put it in here or it might muddle the point of this post but it fairly trivial).
The scene loader can be added to the sharedLoaderLibrary with the following two lines:
var nodeLibrary = cc.NodeLoaderLibrary.sharedCCNodeLoaderLibrary();
nodeLibrary.registerCCNodeLoader("TestScene", TestSceneLoader.loader());
To make this work two changes need to be made to the CCBReader code. Above we are using the sharedCCNodeLoaderLibrary but in the CCBReader.js class a new nodeloaderlibrary is created by default. It really should be a parameter passed in but to get it using the sharedlibrary change the following line (823) from:
var reader = new cc.BuilderReader(cc.NodeLoaderLibrary.newDefaultCCNodeLoaderLibrary());
to:
var reader = new cc.BuilderReader(cc.NodeLoaderLibrary.sharedCCNodeLoaderLibrary());
I think in general the CCBReader.js is currently broken as there is no defined way to change the loader library. I suspect this is going to be done in a future version.
The second change that needs to be made is to remove the restriction on determining the animation nodes and managers to be a JSControlled action only (line 246) by commenting out the if statement:
// if (this._jsControlled) {
this._nodesWithAnimationManagers = [];
this._animationManagerForNodes = [];
var getAllKeys = this._animationManagers.allKeys();
for (var i = 0; i < getAllKeys.length; i++) {
this._nodesWithAnimationManagers.push(getAllKeys[i]);
this._animationManagerForNodes.push(this._animationManagers.objectForKey(getAllKeys[i]));
}
// }
This seems to allow me to animate and interact with the scenes without having the additional JSControlled flag (meaning my content creators are completely language agnostic … the way I want it to be).
I’m wondering if I have done something very wrong here or missed the point, but for now I am happy that I can create scenes for multiple platforms without extra fields. I’m also wondering how much the CCBReader code will change over time given that the code sitting in the library (i.e. the nodeloaderlibrary) is essentially unusable unless you start altering the code in the library.
To me it would have made more sense to preserve the Cocosbuilder client and have no additional changes required on that side. The files spat out for any language would be the same. It then is the job of the CocosBuilder library to make it easy for the developer to stitch the screens in as seamlessly as possible in the language of choice. Given the dynamic nature of JS this could have been done much more in the obj-c way but equally validly (for porting reasons) could have been done in the cocos2d-x way. Instead, however, we seem to have a third way which doesn’t preserve the same integrity towards cocos classes that the other languages did. I’d love to know if there are some good reasons for doing this that I have missed.