Understanding Cocosbuilder usage in the HTML5 framework

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.

Hi there,

Interesting post. I am relatively new to this and have been playing around with CocosBuilder and Cocos2D-HTML5 for a couple of weeks. Seeing as the tools and the code are changing frequently and this post was made 4 months ago, I would be interested to see what your current experience is.

I have downloaded CocosBuilder 3.0 which generated ccbi files of version 5, when I used the latest stable version of Cocos2D-HTML5, it only supported version 4. So I clone the latest development version of Cocos2D-HTML5 and it loaded the file. Only to then find that the ccbi file had an unsupported flag of “isTouchEnabled” (Cocos2D-HTML5 was looking for “touchEnabled”). So I modified the code in CCSpriteLoader to the former and it loaded, but couldn’t see anything on the screen (I could see that the assets were being requested).

I am trying to get a handle on what are the best versions of the tools to be working with as of April 23rd, 2013… Any thoughts? Do you still use the same procedure you mentioned above?

Cheers…

Hi Nathan,

We still continue to use CocosBuilder and Cocos2d-html5 in the same way as above. Being able to change the loaders is critical to us. I can do some very interesting things to create dynamic change by just changing the loaders. For example we use CCColorLayer with a special class type that allow the color to be altered when loading (information I only know at run time) just by altering how the loader reacts to custom properties. Otherwise the loader is identical to the base loaders within the CCBReader extension.

The code I am using is based off of the released v2.1.1. I haven’t moved to the v2.1.2 release (I plan to migrate in the next week or so). I would go with the latest versions although I am not completely sure I can still do things in the same way as before but I am sure I can get things working the way I would like them (i.e. a single content flow for all platforms that can handle dynamic data the way I need to). I will post what I changed in the v2.1.2 migration when I do it.

I also came across the switch on the iTouchEnabled/touchEnabled issue. Seems like the properties changed without the CCBReader being updated. Here are the changes I made in the CCSpriteLoader to make that work (starting at line 80)

var PROPERTY_TOUCH_ENABLED = "touchEnabled";
var PROPERTY_IS_TOUCH_ENABLED = "isTouchEnabled";
var PROPERTY_ACCELEROMETER_ENABLED = "accelerometerEnabled";
var PROPERTY_IS_ACCELEROMETER_ENABLED = "isAccelerometerEnabled";
var PROPERTY_IS_MOUSE_ENABLED = "isMouseEnabled";
var PROPERTY_MOUSE_ENABLED = "mouseEnabled";
var PROPERTY_KEYBOARD_ENABLED = "keyboardEnabled";
var PROPERTY_IS_KEYBOARD_ENABLED = "isKeyboardEnabled";

cc.LayerLoader = cc.NodeLoader.extend({
    _createCCNode:function (parent, ccbReader) {
        return cc.Layer.create();
    },
    onHandlePropTypeCheck:function (node, parent, propertyName, check, ccbReader) {
        if (propertyName == PROPERTY_TOUCH_ENABLED || propertyName == PROPERTY_IS_TOUCH_ENABLED) {
            node.setTouchEnabled(check);
        } else if (propertyName == PROPERTY_ACCELEROMETER_ENABLED || propertyName == PROPERTY_IS_ACCELEROMETER_ENABLED) {
            node.setAccelerometerEnabled(check);
        } else if (propertyName == PROPERTY_IS_MOUSE_ENABLED || propertyName == PROPERTY_MOUSE_ENABLED ) {
            node.setMouseEnabled(check)
        } else if (propertyName == PROPERTY_KEYBOARD_ENABLED || propertyName == PROPERTY_IS_KEYBOARD_ENABLED) {
            // TODO XXX
            cc.log("The property '" + PROPERTY_KEYBOARD_ENABLED + "' is not supported!");
            // This comes closest: ((CCLayer *)pNode).setKeypadEnabled(pCheck);
        } else {
            this._super(node, parent, propertyName, check, ccbReader);
        }
    }
});

Not a big fan of the above. Would have hoped this had been fixed in the latest version (or maybe more was introduced).

Alan

Thanks Alan,

I didn’t realise there was a 2.1.2. Can you tell me where to find that?

It’s part of the coordinated release

http://cocos2d-x.org/news/95

That should solve any version number discrepancies you were having.

Hi Alan,

Which version of CocosBuilder are you using? I am experiencing some inconsistencies using v3 of CocosBuilder which is understandable as it is in Alpha. But I get the impression that is the only version to use if you want Javascript support. Are you also using v3 Alpha?

The main inconsistency I can see is the naming of resources and how the different versions of CCBReader looks for them (depends on whether you are using Cocos2DX or Cocos2D-iPhone and then it depends on what version you are using). From the Cocosbuilder docs its says to use the resources-auto approach. But the Cocos2DX docs want you to specify a search path in the latest release.

Another question. At the moment I am just doing my app for HTML5 and my client is hoping to be able to release it onto iOS and Android later on. Do you think I would be best to use Cocos2DX for deployment to both platforms or just use Cocos2DX for Android and use the iPhone library for iOS… I can’t see any particular recommendation online for this, maybe it doesn’t matter?

Any thoughts on the above?

I am trying your loading technique with cocos2d-html5 v2.1.1 - And i am assuming you are using CocosBuilder V2.1? v2.1.1 of the library has a CCBREADER version of 4, while CocosBuilder 2.1 generates version 3 files…Did you get an older copy of CCBReader or customise it specifically… If you were using CocosBuilder Alpha 3… then the CCBREADER version would be 5 which is still no good

Looking at the code on Github there doesn’t seem to be a version of CCBReader that supports version 3 files… gonna try and use cocos2d-html5 v2.1.1 and just update the CCBReader version to the latest on Github so it works with CocosBuilderAlpha v3 ccbi exports.

Hi Nathan,

Sorry for the delayed reply :slight_smile:

I am still on the 2nd coordinated release from a few months back

http://cocos2d-x.org/news/85

The point of the coordinated release was to avoid some of the versioning issues you are having. The CocosBuilder version that came out in that release was 3.0-alpha1.

If you begin to mix and match you are probably better served by looking at incremental builds in the github repos.

Although I would like to move to the latest version of CocosBuilder (or at least the version in the 3rd coordinated release), I am a little worried by some of the feedback to cocos2d-html5 2.1.2 (particularly because I display on mobile webviews … and from what I can tell most improvements in the build aren’t going to help me … and some of the changes might hurt me).

You’ll have to decide on your project if you need the latest and greatest (both in features and stability) because to be coordinated the best bet is probably the 3rd coordinated release I indicated above. As with any open source platform YMMV. There will be some bugs you need to work around (there are things which make cocosbuilder crash. We just don’t do those things anymore :). There may be some show stoppers you need to code around as well.

As far as multi platform approaches … I have not yet tried to deliver cocos2d-html5 via javascript bindings as a native app. It will perform slower than writing it in cocos2d-x or cocos2d-iphone but you might not need the speed. What is probably more appropriate to think about (if you can sacrifice the performance), is that cocos2d-html5 is much younger than the other platforms and the JS bindings even younger than that. Approach with trepidation and be prepared to have to roll up your sleeves to make things work.

The alternative is to use some combination of cocos2d platforms across the different hardware platforms you want to deliver against. I will say that in the last few months I have written full published games in cocos2d-x, cocos2d-iphone, and cocos2d-html5. Converting from one of these languages to another is not very hard. I wrote the same game for Android using 2d-x and iOS using 2d-iphone. I think overall it probably took me about the same time as it would have if I did a single code base in 2d-x (I wrote it on iphone first and then translated it). The game wasn’t very complicated though so having two copies of the same game code wasn’t an overriding concern (and seeing how each of the platforms worked was one of the objectives). Dealing with 3rd-party solutions written natively for android in Java or for iOS in Obj-c is always an extra time sink with cocos2d-x (either finding or building the necessary bridge code). Hands down the easiest, fastest, most efficient and elegant way to write a game for iOS with cocos2d is via cocos2d-iphone (for me that is). If that is your lead platform and the one that really matters you should keep that in mind.

Alan

Thanks for the detailed response Alan, I will check out the other co-ordinated release you mentioned.

I thought the idea behind the Javascript bindings was that it wouldn’t really impact on performance since its making native calls anyway? There must be some performance overhead to be able to do this, but I would think that it would be small. I guess it needs to interpret the script at runtime though.

The main reason I am checking this out is that I was approached by a friend who had a bunch of simple interactive stories in Flash (a common scenario I imagine - “get my flash stuff online!”) that they wanted to be viewable on mobile devices. So I was planning on rewriting their engine using cocos2d-html5 and introducing them a flash like interface in cocosbuilder (makes sense to me). This would allow them to have their content viewable on both desktop and mobile and then later on, they could reuse this new engine inside their mobile specific app. The ccbi scenes are not intensive, just one CCLabelBMFont instance and sometimes an animation. Buuuut, I am also doing this prototype as I don’t really want to introduce them to something that is potentially going to change a lot in a short amount of time. I would hate to recommend this solution, get them to do a bunch of work in generating CCBI files and then find out that the file format changes or something of that nature…

The engine that displays the stories is very simple, so I guess I could port it to the native codebase at a later stage, but its so simple I doubt I would probably see a peformance improvement.

Appreciate the info, its pretty quiet on these forums, so its nice to get some feedback… cheers.

It appears as thought CocosBuilder 3.0 Alpha 1 is no longer available for Download on their website…

That’s disappointing. If you went to their github repo it is probably labelled but not sure if all the files needed are there.

As far as JS binding performance … for me it isn’t just the performance (which will take some hit … but might be negligible), its also about access to services (platform and 3rd party).

As far as your use case it sounds like it isn’t super heavy. Have you considered other platforms that are vying to replace Flash in the new HTML5 world?

Off the top of my head there is EaselJS … and CAAT (from Ludei … which makes CocoonJS that might really fit your needs … I know these guys and they are good).

Great, thanks for the alternatives… CAAT looks great.

I guess the other big criteria is the GUI for creating content which is what drew me to CocosBuilder. The people who will be converting the content will need a GUI as they are not developers… Trying to find something for CAAT but no luck so far. Thats a shame, looks like it would be perfect.