Skip to content

hailua54/hello_cocosjs

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Simple typescript project structure for COCOSJS

Setup

create project

  • command:

    cocos new -l js -p com.vgame.hello_cocosjs hello_cocosjs

    "com.vgame.hello_cocosjs" will be

      applicationId in frameworks\runtime-src\proj.android-studio\app\build.gradle
      
      package="com.vgame.hello_cocosjs" in frameworks\runtime-src\proj.android-studio\app\AndroidManifest.xml
    

Initialize

  • Modify project.json (no more load app.js)

     "jsList" : [
     "src/resource.js",
     "src/game.js"
  • Modify main.js to create Game object

     cc.LoaderScene.preload(g_resources, function () {
     	//cc.director.runScene(new HelloWorldScene()); 
     	var game = new Game();
     }, this);
  • Modify frameworks/cocos2d-x/cocos/base/CCDirector.cpp

     void Director::reset()
     {   // ...
     	Director::getInstance()->getEventDispatcher()->dispatchCustomEvent("game_on_exit");
     	// ...
     }
  • Modify timlineParser-2.x.js

     register.forEach(function(item){
         parser.registerParser(item.name, function(options, resourcePath){
             var node = item.handle.call(this, options, resourcePath);
             this.parseChild(node, options["Children"], resourcePath);
     		if (node['onUIParseComplete']) node['onUIParseComplete']();
     		if (!isShowBackGroundColorOpacity && node.setBackGroundColorOpacity) node.setBackGroundColorOpacity(0);
             DEBUG && node && (node.__parserName = item.name);
             return node;
         });
     });
     
     parser.initSingleNode = function(json, resourcePath){
         var node = json.UserData?eval('new ' + json.UserData + '()'):new cc.Node();
     	//...
     }
  • Add "..Sdk\platform-tools" to system variable 'Path' to be able to use 'adb' command

  • frameworks\cocos2d-x\cocos\platform\android\jni\Java_org_cocos2dx_lib_Cocos2dxRenderer.cpp

     JNIEXPORT void JNICALL Java_org_cocos2dx_lib_Cocos2dxRenderer_nativeOnPause() {
         if (Director::getInstance()->getOpenGLView()) {
                 //Application::getInstance()->applicationDidEnterBackground();
                 cocos2d::EventCustom backgroundEvent(EVENT_COME_TO_BACKGROUND);
                 cocos2d::Director::getInstance()->getEventDispatcher()->dispatchEvent(&backgroundEvent);
                 Director::getInstance()->getEventDispatcher()->dispatchCustomEvent("custom_game_event_hide");
         }
     }
  • frameworks\cocos2d-x\cocos\platform\android\java\src\org\cocos2dx\lib\Cocos2dxGLSurfaceView.java

     @Override
     public void onPause() {
         this.queueEvent(new Runnable() {
             @Override
             public void run() {
                Cocos2dxGLSurfaceView.this.mCocos2dxRenderer.handleOnPause();
             }
         });
         //this.setRenderMode(RENDERMODE_WHEN_DIRTY);
         //super.onPause();
     }
     
     Cocos2dxGLSurfaceView.sHandler = new Handler() {
     	@Override
     	public void handleMessage(final Message msg) {
     		switch (msg.what) {
     			case HANDLER_OPEN_IME_KEYBOARD:
     				Cocos2dxGLSurfaceView.this.mCocos2dxEditText.setVisibility(View.VISIBLE);
     				//Cocos2dxGLSurfaceView.mCocos2dxGLSurfaceView.setVisibility(View.GONE);
     				Cocos2dxGLSurfaceView.cppOnOpenIMEKeyboard(true);
     				//...
     				break;
    
     			case HANDLER_CLOSE_IME_KEYBOARD:
     				Cocos2dxGLSurfaceView.this.mCocos2dxEditText.setVisibility(View.GONE);
     				//Cocos2dxGLSurfaceView.mCocos2dxGLSurfaceView.setVisibility(View.VISIBLE);
     				Cocos2dxGLSurfaceView.cppOnOpenIMEKeyboard(false);
     				//...
     				break;
     		}
     	}
     };
     
     public static native void cppOnOpenIMEKeyboard(boolean isOpen);

Compile

  • web: cocos compile -p web -m release --advanced

  • Android studio:

    AppDelegate.cpp:

     static u_long myNextRandom = 1;
     double atof(const char *nptr)
     {
     return (strtod(nptr, NULL));
     }
    
     int rand(void)
     {
     return (int)((myNextRandom = (1103515245 * myNextRandom) + 12345) % ((u_long)RAND_MAX + 1));
     }
    
     void srand(u_int seed)
     {
     myNextRandom = seed;
     }
    • build bug report frameworks\runtime-src\proj.android-studio\app\build\outputs\logs

Tip

References

  • Android VideoPlayer: check frameworks\cocos2d-x\cocos\ui\UIVideoPlayer-android.cpp :

  • Android Flow:

    • Build libcocos2dandroid:

      frameworks\cocos2d-x\cocos\platform\android\Android.mk ( ... javaactivity-android.cpp \ ...)

      javaactivity-android.cpp => frameworks\runtime-src\proj.android-studio\app\jni\hellojavascript\main.cpp:

      1. cocos_android_app_init(JniHelper::getEnv());

      2. init C++ for java to call via jni:

       // in frameworks\cocos2d-x\cocos\platform\android\javaactivity-android.cpp
       JNIEXPORT void Java_org_cocos2dx_lib_Cocos2dxRenderer_nativeInit(JNIEnv*  env, jobject thiz, jint w, jint h)
       {
       	auto director = cocos2d::Director::getInstance();
       	auto glview = director->getOpenGLView();
       	if (!glview)
       	{
       		glview = cocos2d::GLViewImpl::create("Android app");
       		glview->setFrameSize(w, h);
       		director->setOpenGLView(glview);
      
       		cocos2d::Application::getInstance()->run();
       	}
       	else
       	{
       		//...
       	}
       	cocos2d::network::_preloadJavaDownloaderClass();
       }
       
       
       // in frameworks\cocos2d-x\cocos\platform\android\jni\Java_org_cocos2dx_lib_Cocos2dxRenderer.cpp
       
       JNIEXPORT void JNICALL Java_org_cocos2dx_lib_Cocos2dxRenderer_nativeRender(JNIEnv* env) {
       	cocos2d::Director::getInstance()->mainLoop();
       }

      frameworks\cocos2d-x\cocos\platform\android\java\src\org\cocos2dx\lib\Cocos2dxRenderer.java:

       @Override
       public void onSurfaceCreated(final GL10 GL10, final EGLConfig EGLConfig) {
       	Cocos2dxRenderer.nativeInit(this.mScreenWidth, this.mScreenHeight);
       	this.mLastTickInNanoSeconds = System.nanoTime();
       	mNativeInitCompleted = true;
       }
       
       public void onDrawFrame(GL10 unused)
       
       public void onSurfaceChanged(GL10 unused, int width, int height)

      check: http://cnguyen93.blogspot.com/2014/03/khoi-tao-opengl-es-20-tren-android.html

  • GC

    http://wiki.luajit.org/New-Garbage-Collector#gc-algorithms_two-color-mark-sweep

    Ruby 2.2 GC

    https://engineering.heroku.com/blogs/2015-02-04-incremental-gc/

  • Touch events

    http://www.cocos2d-x.org/wiki/EventDispatcher_Mechanism

  • Resolution policy: check CCEGLView.js

     _setupContainer: function (view, w, h) {
         var locCanvas = cc.game.canvas, locContainer = cc.game.container;
         if (cc.sys.isMobile) {
             document.body.style.width = (view._isRotated ? h : w) + 'px';
             document.body.style.height = (view._isRotated ? w : h) + 'px';
         }
    
         // Setup style
         locContainer.style.width = locCanvas.style.width = w + 'px';
         locContainer.style.height = locCanvas.style.height = h + 'px';
         // Setup pixel ratio for retina display
         var devicePixelRatio = view._devicePixelRatio = 1;
         if (view.isRetinaEnabled())
             devicePixelRatio = view._devicePixelRatio = Math.min(2, window.devicePixelRatio || 1);
         // Setup canvas
         locCanvas.width = w * devicePixelRatio;
         locCanvas.height = h * devicePixelRatio;
         cc._renderContext.resetCache && cc._renderContext.resetCache();
     }
  • Load image from server:

     cc.loader.loadImg(url, {isCrossOrigin: false}, function(error:any, img:any){
     if (error) return;
     if (isWeb())
     {
     	var avatarTex = new cc.Texture2D();
     	avatarTex.initWithElement(img);
     	avatarTex.handleLoadedTexture();
     	var avatar = new cc.Sprite(avatarTex);
     	this.resizeAvatar(avatar);
     }
     else {
     	var avatar = new cc.Sprite();
     	avatar.initWithTexture(img);
     	this.resizeAvatar(avatar);
     }
     }.bind(this));
     
  • webgl:

     //RendererWebGL.js 
     _clearColor: cc.color(0,0,0,0),                            //background color,default BLACK
     
     // CCBoot.js
     cc.create3DContext = function (canvas, opt_attribs) {
     	var names = ["webgl", "experimental-webgl", "webkit-3d", "moz-webgl"];
     	var context = null;
     	for (var ii = 0; ii < names.length; ++ii) {
     		try {
     			context = canvas.getContext(names[ii], { premultipliedAlpha: false });
     		} catch (e) {
     		}
     		if (context) {
     			break;
     		}
     	}
     	return context;
     };
  • JS call C++ sample:

    custom_binding.h:

     
     #include "jsapi.h"
    
     extern JSClass  *jsb_CppUtils_class;
     extern JSObject *jsb_CppUtils_prototype;
    
     bool js_sys_CppUtils_getOrientation(JSContext *cx, uint32_t argc, jsval *vp);
     void js_register_sys_CppUtils(JSContext *cx, JS::HandleObject global);

    custom_binding.cpp:

     
     #include "custom_binding.h"
     #include "sys_init.h"
     #include "scripting/js-bindings/manual/ScriptingCore.h"
     #include "scripting/js-bindings/manual/js_manual_conversions.h"
    
     JSClass  *jsb_sys_CppUtils_class;
     JSObject *jsb_cocos2d_sys_CppUtils_prototype;
    
     static bool empty_constructor(JSContext *cx, uint32_t argc, jsval *vp) {
     	return false;
     }
    
     static bool js_is_native_obj(JSContext *cx, uint32_t argc, jsval *vp)
     {
     	JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
     	args.rval().setBoolean(true);
     	return true;
     }
    
     bool js_sys_CppUtils_getOrientation(JSContext *cx, uint32_t argc, jsval *vp)
     {
     	JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
    
     	if (argc == 0) {
     		int orientation = sys::cpp_2_native_getOrientation();
     		args.rval().setInt32(orientation);
     		return true;
     	}
    
     	JS_ReportError(cx, "js_sys_CppUtils_getOrientation : wrong number of arguments: %d, was expecting %d", argc, 0);
     	return false;
     }
    
     void js_register_sys_CppUtils(JSContext *cx, JS::HandleObject global)
     {
     	jsb_sys_CppUtils_class = (JSClass *)calloc(1, sizeof(JSClass));
     	jsb_sys_CppUtils_class->name = "CppUtils";
     	jsb_sys_CppUtils_class->addProperty = JS_PropertyStub;
     	jsb_sys_CppUtils_class->delProperty = JS_DeletePropertyStub;
     	jsb_sys_CppUtils_class->getProperty = JS_PropertyStub;
     	jsb_sys_CppUtils_class->setProperty = JS_StrictPropertyStub;
     	jsb_sys_CppUtils_class->enumerate = JS_EnumerateStub;
     	jsb_sys_CppUtils_class->resolve = JS_ResolveStub;
     	jsb_sys_CppUtils_class->convert = JS_ConvertStub;
     	jsb_sys_CppUtils_class->flags = JSCLASS_HAS_RESERVED_SLOTS(2);
    
     	static JSPropertySpec properties[] = {
     		JS_PS_END
     	};
    
     	static JSFunctionSpec funcs[] = {
     		JS_FS_END
     	};
    
     	static JSFunctionSpec st_funcs[] = {
     		JS_FN("getOrientation", js_sys_CppUtils_getOrientation, 0, JSPROP_PERMANENT | JSPROP_ENUMERATE),
     		JS_FS_END
     	};
    
     	jsb_cocos2d_sys_CppUtils_prototype = JS_InitClass(
     		cx, global,
     		JS::NullPtr(),
     		jsb_sys_CppUtils_class,
     		empty_constructor, 0,
     		properties,
     		funcs,
     		NULL, // no static properties
     		st_funcs);
    
     	JS::RootedObject proto(cx, jsb_cocos2d_sys_CppUtils_prototype);
     	JS::RootedValue className(cx, std_string_to_jsval(cx, "CppUtils"));
     	JS_SetProperty(cx, proto, "_className", className);
     	JS_SetProperty(cx, proto, "__nativeObj", JS::TrueHandleValue);
     	JS_SetProperty(cx, proto, "__is_ref", JS::TrueHandleValue);
     	// add the proto and JSClass to the type->js info hash table
     	jsb_register_class<sys::CppUtils>(cx, jsb_sys_CppUtils_class, proto, JS::NullPtr());
     }
  • C++ call JS, C++ call Native, Native call C++:

    sys_init.h:

     #ifndef  _SYS_INIT_H_
     #define  _SYS_INIT_H_
     namespace sys
     {
     	void cpp_2_js_orientationChange(int oritentation);
     	int cpp_2_native_getOrientation();
    
     	// dummy class for jsbinding
     	class CppUtils
     	{
     		// JS:
     		// public static int getOrientation();
     	};
     }
     #endif

    sys_init.cpp:

     #include "sys_init.h"
     #include "cocos2d.h"
     #include "scripting/js-bindings/manual/ScriptingCore.h"
     USING_NS_CC;
    
     #if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
     #include <jni.h>
     #include "platform/android/jni/JniHelper.h"
     #endif
    
     #if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
     // custom cpp functions for Java to call
     extern "C"
     void Java_org_cocos2dx_javascript_NativeCppFunctions_cppOrientationChange(JNIEnv* env, jobject /* this */, jint orientation)
     {
     	int orient = orientation;
     	// should call the function in cocos thread http://discuss.cocos2d-x.org/t/solved-calling-javascript-from-c-crashes-on-android/22805/3
     	Director::getInstance()->getScheduler()->performFunctionInCocosThread([=] {
     		CCLOG("Java_org_cocos2dx_javascript_NativeCppFunctions_cppOrientationChange %d ", orient);
     		sys::cpp_2_js_orientationChange(orient); 
     	});
     }
    
     // custom cpp functions for Java to call
     extern "C"
     void Java_org_cocos2dx_lib_Cocos2dxGLSurfaceView_cppOnOpenIMEKeyboard(JNIEnv* env, jobject /* this */, jboolean isOpen)
     {
     	bool opened = isOpen;
     	Director::getInstance()->getScheduler()->performFunctionInCocosThread([=] {
     		CCLOG("Java_org_cocos2dx_lib_Cocos2dxGLSurfaceView_cppOnOpenIMEKeyboard %d ", opened);
     		if (opened) Director::getInstance()->getEventDispatcher()->dispatchCustomEvent("IME_keyboard_open");
     		else
     		{
     			Director::getInstance()->getEventDispatcher()->dispatchCustomEvent("IME_keyboard_close");
     		}
     	});
     }
     #endif
    
     void sys::cpp_2_js_orientationChange(int oritentation)
     {
     	
     	ScriptingCore * scriptingCore = ScriptingCore::getInstance();
    
     	JSContext * cx = scriptingCore->getGlobalContext();
     	JS::RootedObject object(cx, scriptingCore->getGlobalObject());
     	JS::RootedValue owner(cx);
    
     	jsval args[1];
     	JS_GetProperty(cx, object, "sys", &owner);
    
     	args[0] = INT_TO_JSVAL(oritentation);
    
     	scriptingCore->executeFunctionWithOwner(owner, "onOrientationChange", 1, args);
     }
    
     int sys::cpp_2_native_getOrientation()
     {
     	int orientation = 1;
     #if CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID
     	JniMethodInfo t;
     	if (JniHelper::getStaticMethodInfo(t, "org/cocos2dx/javascript/ExportJavaFunctions", "androidGetOrientation", "()I"))
     	{
     		jint retV = t.env->CallStaticIntMethod(t.classID, t.methodID);
     		t.env->DeleteLocalRef(t.classID);
     		orientation = retV;
     	}
     #endif
     	return orientation;
     }

    sysinit.js

     var CppUtils = eval('CppUtils');
  • Java call C++:

    http://stnguyen.com/cocos2d-x/call-cpp-functions-from-java.html

  • C++ call Java:

    http://stnguyen.com/cocos2d-x/call-java-functions-from-cpp.html

  • Build:

  • Video Player:

    • Binding:

      frameworks\cocos2d-x\cocos\scripting\js-bindings\manual\experimental\jsb_cocos2dx_experimental_video_manual.cpp

      static bool jsb_cocos2dx_experimental_ui_VideoPlayer_addEventListener(JSContext *cx, uint32_t argc, jsval *vp)
      {
      	JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
      	JS::RootedObject obj(cx, args.thisv().toObjectOrNull());
      	js_proxy_t *proxy = jsb_get_js_proxy(obj);
      	experimental::ui::VideoPlayer* cobj = (experimental::ui::VideoPlayer *)(proxy ? proxy->ptr : NULL);
      	JSB_PRECONDITION2( cobj, cx, false, "Invalid Native Object");
      
      	if(argc == 1){
      		std::shared_ptr<JSFunctionWrapper> func(new JSFunctionWrapper(cx, obj, args.get(0)));
      		cobj->addEventListener([=](Ref* widget, experimental::ui::VideoPlayer::EventType type)->void{
      			jsval arg[2];
      			JS::RootedObject jsobj(cx, js_get_or_create_jsobject<Ref>(cx, widget));
      			arg[0] = OBJECT_TO_JSVAL(jsobj);
      			arg[1] = int32_to_jsval(cx, (int32_t)type);
      			JS::RootedValue rval(cx);
      
      			bool ok = func->invoke(2, arg, &rval);
      			if (!ok && JS_IsExceptionPending(cx)) {
      				JS_ReportPendingException(cx);
      			}
      		});
      		return true;
      	}
      
      	JS_ReportError(cx, "jsb_cocos2dx_experimental_ui_VideoPlayer_addEventListener : wrong number of arguments: %d, was expecting %d", argc, 1);
      	return false;
      }

      frameworks\cocos2d-x\cocos\scripting\js-bindings\auto\jsb_cocos2dx_experimental_video_auto.cpp

      bool js_cocos2dx_experimental_video_VideoPlayer_onPlayEvent(JSContext *cx, uint32_t argc, jsval *vp)
      {
      	JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
      	bool ok = true;
      	JS::RootedObject obj(cx, args.thisv().toObjectOrNull());
      	js_proxy_t *proxy = jsb_get_js_proxy(obj);
      	cocos2d::experimental::ui::VideoPlayer* cobj = (cocos2d::experimental::ui::VideoPlayer *)(proxy ? proxy->ptr : NULL);
      	JSB_PRECONDITION2( cobj, cx, false, "js_cocos2dx_experimental_video_VideoPlayer_onPlayEvent : Invalid Native Object");
      	if (argc == 1) {
      		int arg0 = 0;
      		ok &= jsval_to_int32(cx, args.get(0), (int32_t *)&arg0);
      		JSB_PRECONDITION2(ok, cx, false, "js_cocos2dx_experimental_video_VideoPlayer_onPlayEvent : Error processing arguments");
      		cobj->onPlayEvent(arg0);
      		args.rval().setUndefined();
      		return true;
      	}
      
      	JS_ReportError(cx, "js_cocos2dx_experimental_video_VideoPlayer_onPlayEvent : wrong number of arguments: %d, was expecting %d", argc, 1);
      	return false;
      }
    • JS code:

      frameworks\cocos2d-x\cocos\scripting\js-bindings\script\ccui\jsb_cocos2d_ui.js

       ccui.VideoPlayer.prototype.setEventListener = function(event, callback){
       	if (!this.videoPlayerCallback)
       	{
       		this.videoPlayerCallback = function(sender, eventType){
       			cc.log("videoEventCallback eventType:" + eventType);
       			switch (eventType) {
       				case 0:
       					this["VideoPlayer_"+ccui.VideoPlayer.EventType.PLAYING] && this["VideoPlayer_"+ccui.VideoPlayer.EventType.PLAYING](sender);
       					break;
       				case 1:
       					this["VideoPlayer_"+ccui.VideoPlayer.EventType.PAUSED] && this["VideoPlayer_"+ccui.VideoPlayer.EventType.PAUSED](sender);
       					break;
       				case 2:
       					this["VideoPlayer_"+ccui.VideoPlayer.EventType.STOPPED] && this["VideoPlayer_"+ccui.VideoPlayer.EventType.STOPPED](sender);
       					break;
       				case 3:
       					this["VideoPlayer_"+ccui.VideoPlayer.EventType.COMPLETED] && this["VideoPlayer_"+ccui.VideoPlayer.EventType.COMPLETED](sender);
       					break;
       				default:
       					break;
       			}
       		};
       		this.addEventListener(this.videoPlayerCallback);
       	}
       	this["VideoPlayer_"+event] = callback;
       };
    • Andoid cpp:

      frameworks\cocos2d-x\cocos\ui\UIVideoPlayer-android.cpp

       
       #include "ui/UIVideoPlayer.h"
       
       //...
       
       void VideoPlayer::addEventListener(const VideoPlayer::ccVideoPlayerCallback& callback)
       {
       	_eventCallback = callback;
       }
  • AssetManager http://www.cocos2d-x.org/docs/creator/en/advanced-topics/assets-manager.html

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published