Slide 1

Slide 1 text

Making games using JavaScript and Cocos2D Taras Tovchenko LevelUp email: [email protected] skype: tarastovchenko icq: 146687 twitter: @doctorset

Slide 2

Slide 2 text

Plan • A quick guide of Cosos2D • The JavaScript propagation • JavaScript binding • Espreso framework • Cocos2d: Tools & Libs

Slide 3

Slide 3 text

Cocos2D framework

Slide 4

Slide 4 text

Cocos2D framework

Slide 5

Slide 5 text

Cocos2D comparison: WEB engines

Slide 6

Slide 6 text

Cocos2D comparison: Native platforms ?

Slide 7

Slide 7 text

JavaScript propagation Every thing goes to simplified and useful form, nobody wants to make simple thing through the hard way. And JavaScript gives this advantage.

Slide 8

Slide 8 text

JavaScript propagation: Obvious benefits • You can hire several senior developers for supporting core functionality - shaders, native features, engine and etc. • And hire a log of juniors (students for instance) for developing game mechanics. • Less money - more games!

Slide 9

Slide 9 text

JavaScript propagation was created in 1995 for the Web in 2009 was developed server-side framework how can we use it on the other platforms?

Slide 10

Slide 10 text

JavaScript and native API

Slide 11

Slide 11 text

JavaScript binding JSB was developed a few years ago by Zynga The JS code is interpreted by SpiderMonkey, Mozilla's JS virtual machine JSB allows calling native code from JS and vice- versa.

Slide 12

Slide 12 text

Unity 3D supports JavaScript too And Unity supports JS before Zynga

Slide 13

Slide 13 text

JavaScript binding: Native C++ class class EspresoAction : public cocos2d::Action { public: static EspresoAction* create(); virtual std::string description() const; virtual cocos2d::Action* clone() const; virtual cocos2d::Action* reverse() const; virtual bool isDone() const { return cocos2d::Action::isDone(); } virtual void startWithTarget(cocos2d::Node *target); virtual void stop() { cocos2d::Action::stop(); } virtual void step(float dt); virtual void update(float time) { cocos2d::Action::update(time); } cocos2d::Node* getTarget() const { return cocos2d::Action::getTarget(); } void setTarget(cocos2d::Node *target) { cocos2d::Action::setTarget(target); } cocos2d::Node* getOriginalTarget() const; void setOriginalTarget(cocos2d::Node *originalTarget); int getTag() const { return cocos2d::Action::getTag(); } void setTag(int tag) { cocos2d::Action::setTag(tag); } protected: EspresoAction() {} };

Slide 14

Slide 14 text

JavaScript binding: Parsed interface extern JSClass *jsb_es_EspresoAction_class; extern JSObject *jsb_es_EspresoAction_prototype; bool js_espreso_EspresoAction_constructor(JSContext *cx, uint32_t argc, jsval … void js_espreso_EspresoAction_finalize(JSContext *cx, JSObject *obj); void js_register_espreso_EspresoAction(JSContext *cx, JSObject *global); void register_all_espreso(JSContext* cx, JSObject* obj); bool js_espreso_EspresoAction_startWithTarget(JSContext *cx, uint32_t argc, … bool js_espreso_EspresoAction_setOriginalTarget(JSContext *cx, uint32_t argc, … bool js_espreso_EspresoAction_clone(JSContext *cx, uint32_t argc, jsval *vp); bool js_espreso_EspresoAction_getOriginalTarget(JSContext *cx, uint32_t argc, … bool js_espreso_EspresoAction_stop(JSContext *cx, uint32_t argc, jsval *vp); bool js_espreso_EspresoAction_update(JSContext *cx, uint32_t argc, jsval *vp); bool js_espreso_EspresoAction_getTarget(JSContext *cx, uint32_t argc, jsval *vp); bool js_espreso_EspresoAction_setTag(JSContext *cx, uint32_t argc, jsval *vp); bool js_espreso_EspresoAction_getTag(JSContext *cx, uint32_t argc, jsval *vp); bool js_espreso_EspresoAction_setTarget(JSContext *cx, uint32_t argc, jsval *vp); bool js_espreso_EspresoAction_isDone(JSContext *cx, uint32_t argc, jsval *vp); bool js_espreso_EspresoAction_reverse(JSContext *cx, uint32_t argc, jsval *vp); bool js_espreso_EspresoAction_create(JSContext *cx, uint32_t argc, jsval *vp);

Slide 15

Slide 15 text

JavaScript binding: Parsed code bool js_espreso_EspresoAction_startWithTarget(JSContext *cx, uint32_t argc, jsval *vp) { jsval *argv = JS_ARGV(cx, vp); bool ok = true; JSObject *obj = JS_THIS_OBJECT(cx, vp); js_proxy_t *proxy = jsb_get_js_proxy(obj); es::EspresoAction* cobj = (es::EspresoAction *)(proxy ? proxy->ptr : NULL); JSB_PRECONDITION2( cobj, cx, false, "Invalid Native Object"); if (argc == 1) { cocos2d::Node* arg0; do { if (!argv[0].isObject()) { ok = false; break; } js_proxy_t *jsProxy; JSObject *tmpObj = JSVAL_TO_OBJECT(argv[0]); jsProxy = jsb_get_js_proxy(tmpObj); arg0 = (cocos2d::Node*)(jsProxy ? jsProxy->ptr : NULL); JSB_PRECONDITION2( arg0, cx, false, "Invalid Native Object"); } while (0); JSB_PRECONDITION2(ok, cx, false, "Error processing arguments"); cobj->startWithTarget(arg0); JS_SET_RVAL(cx, vp, JSVAL_VOID); return true; } JS_ReportError(cx, "wrong number of arguments: %d, was expecting %d", argc, 1); return false; }

Slide 16

Slide 16 text

JavaScript binding: Parsed code void js_register_espreso_EspresoAction(JSContext *cx, JSObject *global) { jsb_es_EspresoAction_class = (JSClass *)calloc(1, sizeof(JSClass)); jsb_es_EspresoAction_class->name = "Action"; jsb_es_EspresoAction_class->addProperty = JS_PropertyStub; jsb_es_EspresoAction_class->delProperty = JS_DeletePropertyStub; jsb_es_EspresoAction_class->getProperty = JS_PropertyStub; jsb_es_EspresoAction_class->setProperty = JS_StrictPropertyStub; jsb_es_EspresoAction_class->enumerate = JS_EnumerateStub; jsb_es_EspresoAction_class->resolve = JS_ResolveStub; jsb_es_EspresoAction_class->convert = JS_ConvertStub; jsb_es_EspresoAction_class->finalize = js_es_EspresoAction_finalize; jsb_es_EspresoAction_class->flags = JSCLASS_HAS_RESERVED_SLOTS(2); static JSFunctionSpec funcs[] = { JS_FN("clone", js_espreso_EspresoAction_clone, 0, JSPROP_PERMANENT | JSPROP_ENUMERATE), JS_FN("stop", js_espreso_EspresoAction_stop, 0, JSPROP_PERMANENT | JSPROP_ENUMERATE), JS_FN("update", js_espreso_EspresoAction_update, 1, JSPROP_PERMANENT | JSPROP_ENUMERATE), JS_FN("setTag", js_espreso_EspresoAction_setTag, 1, JSPROP_PERMANENT | JSPROP_ENUMERATE), JS_FN("getTag", js_espreso_EspresoAction_getTag, 0, JSPROP_PERMANENT | JSPROP_ENUMERATE), JS_FN("isDone", js_espreso_EspresoAction_isDone, 0, JSPROP_PERMANENT | JSPROP_ENUMERATE), JS_FN("ctor", js_es_EspresoAction_ctor, 0, JSPROP_PERMANENT | JSPROP_ENUMERATE), JS_FS_END };

Slide 17

Slide 17 text

JavaScript binding: Call native from JS cocos2d::Action* EspresoAction::clone() const { JSB_AUTOCOMPARTMENT_WITH_GLOBAL_OBJCET js_proxy_t* p = jsb_get_native_proxy(const_cast(this)); if (!p) { CCLOG("JSB: Wrong native object = %p", this); return nullptr; } jsval retval; jsval dataVal = INT_TO_JSVAL(1); ScriptingCore::getInstance() ->executeFunctionWithOwner(OBJECT_TO_JSVAL(p->obj), “clone", 1, &dataVal, &retval); return static_cast(JSVAL_TO_PRIVATE(retval)); }

Slide 18

Slide 18 text

JavaScript binding: Tools you must install clang+llvm-3.3 sudo easy_install pip sudo pip install PyYAML sudo pip install Cheetah export NDK_ROOT=/path/to/android-ndk-r9b ./genbindings.py

Slide 19

Slide 19 text

JavaScript binding: Preferences # what headers to parse headers = %(srcdir)s/espreso.h # what classes to produce code for. You can use regular expressions here. When testing the regular # expression, it will be enclosed in "^$", like this: "^Menu*$". classes = EspresoAction EspresoComponent OrientationManager classes_need_extend = EspresoAction EspresoComponent skip = *::[copyWith.* onEnter.* onExit.* ^description$ getObjectType onTouch.* onAcc.* onKey.* onRegisterTouchListener step], OrientationManager::[postOrientation] rename_functions = rename_classes = EspresoComponent::Component, EspresoAction::Action # for all class names, should we remove something when registering in the target VM? remove_prefix = # classes for which there will be no "parent" lookup classes_have_no_parents = EspresoAction EspresoComponent OrientationManager # base classes which will be skipped when their sub-classes found them. base_classes_to_skip = Ref Clonable

Slide 20

Slide 20 text

Android JNI 1. In JNI - Java native code 2. In JSB - Native code JS code In general:

Slide 21

Slide 21 text

JavaScript and Android JNI

Slide 22

Slide 22 text

Espreso engine. (Yes with one “s”) https://github.com/tovchenko/espreso 1. Written in JS 2. Adds extra functionality to Cocos2d 3. Removes cross-platform mistakes 4. Simplify development process

Slide 23

Slide 23 text

Espreso engine: Modules 1. Has component system for audio, flash- animation, frame-animation 2. Supports auto choosing resolution for any screen size with LODs system SD, HD, HDR 3. Adds useful loader, and object builder functional 4. Has a lot different python scripts for resource compiling for different platforms, making texture atlases, sounds, LODs, and etc. 5. Supports CocoStudio UI Editor format for positioning

Slide 24

Slide 24 text

Espreso engine: Objects descriptors "zombie": { "render": { "sprite": "z0_walk_0.png", "atlas": "zombie" }, "sound": { "add": { "src": "bubble_added", "loop": true, "volume": 0.5 }, "destroy": { "src": "bubbles_destroyed" } }, "animator": "zombie_anim.plist", "music": { "level_1": { "src": "music_1", "loop": true, "volume": 0.9 } } }, "popup1": { "data": "mainScene.json" }

Slide 25

Slide 25 text

Espreso engine: Objects var holder = es.PlaceHolder.create(es.utils.getProps(builder.make(‘popup1')), builder); var objects = holder.makeTree(); objects.setPosition(0.5 * size.width, 0.5 * size.height); this.addChild(objects); var drunkard = es.PlaceHolder.getNodeByTag(objects, objs.DRUNKARD0); this._zombie = es.PlaceHolder.getNodeByTag(objects, objs.ZOMBIE); var cat = es.PlaceHolder.getNodeByTag(objects, objs.CAT); drunkard.runAction(es.PlayArmature.create('Action12')); this._zombie.runAction(es.PlayAnimation.create('walk')); this._zombie.runAction(es.PlaySfx.create('add')); this._zombie.runAction(es.PlayMusic.create('level_1'));}

Slide 26

Slide 26 text

Cocos2d: Tools

Slide 27

Slide 27 text

Cocos2d: Tools

Slide 28

Slide 28 text

Cocos2d: Tools CocoStudio

Slide 29

Slide 29 text

Cocos2d: Tools CocoStudio • GUI Editor • Animation Editor with Flash import • Scene editor • Compatible with CocosBuilder • Use CocoStudio instead CocosBuilder • But now available only for Windows platform!

Slide 30

Slide 30 text

Cocos2d: Social & Ads Libs

Slide 31

Slide 31 text

Cocos2d: Social & Ads Libs https://github.com/cocos2d-x/facebook-jsb-sdk

Slide 32

Slide 32 text

Cocos2d: Social & Ads Libs, SOOMLA https://github.com/soomla/cocos2dx-store

Slide 33

Slide 33 text

Thank you for watching! Answers and questions