cocos2dx新创建项目android部分却少build_native.py 文件需要用cocos 命令行进行编译:
基础配置部分: (for mac)
/cocos2d-x-3.x/tools/cocos2d-console/bin下 (ccoos2dx 3.12)
1. chmod u+x cocos.py
2. ./cocos.py new HelloWorldDemo -p com.coco2dx.org -l cpp -d ~/Desktop (创建项目)
3. 先要cd进入proj.android目录 cocos compile -p android (debug 编译)
4. 先要cd进入proj.android目录 cocos compile -p android -m release (release 编译)
5. 下载macport 软件下载:http://www.ccvita.com/434.html(找到对应的操作系统版本)
官网(https://www.macports.org/install.PHP)
- 环境变量设置:
export PATH=/opt/local/bin:$PATH
export PATH=/opt/local/sbin:$PATH
source .bash_profile (修改环境变量)
- 操作指南:
sudo port -v selfupdate (mac ports更新)
port search name (搜索软件)
sudo port install name (安装软件)
sudo port uninstall name (卸载软件)
port outdated (查看软件版本)
sudo port upgrade outdated (升级软件)
- mac port 安卓:
sudo port install python27 py27-yaml py27-cheetah
6. 下来jsbinding一次你就知道有多坑,js版本必须要把原工程的tools拷贝过来(这里可以直接使用cocos2dx引擎下的tools文件夹即可),否则是不可以 pythongenbindings.py 无法使用的,但是lua比较正常;
7. 进入当前生成项目下的tools 中的 tojs文件加,复制一下cocos2dx_experimental_webView.ini进行修改操作,重命名TestJSB.ini;
- 修改项:
[TestJSB]
# the prefix to be added to the generated functions. You might or might not use this in your own
# templates
prefix = TestJSB
# create a target namespace (in javascript,this would create some code like the equiv. to `ns = ns || {}`)
# all classes will be embedded in that namespace
target_namespace = my
macro_judgement = #if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID || CC_TARGET_PLATFORM == CC_PLATFORM_IOS) && !defined(CC_TARGET_OS_TVOS)
android_headers = -I%(androidndkdir)s/platforms/android-14/arch-arm/usr/include -I%(androidndkdir)s/sources/cxx-stl/gnu-libstdc++/4.7/libs/armeabi-v7a/include -I%(androidndkdir)s/sources/cxx-stl/gnu-libstdc++/4.7/include -I%(androidndkdir)s/sources/cxx-stl/gnu-libstdc++/4.8/libs/armeabi-v7a/include -I%(androidndkdir)s/sources/cxx-stl/gnu-libstdc++/4.8/include
android_flags = -D_SIZE_T_DEFINED_
clang_headers = -I%(clangllvmdir)s/lib/clang/%(clang_version)s/include
clang_flags = -nostdinc -x c++ -std=c++11 -U __SSE__
cocos_headers = -I%(cocosdir)s/cocos -I%(cocosdir)s/cocos/editor-support -I%(cocosdir)s/cocos/platform/android
cocos_flags = -DANDROID
cxxgenerator_headers =
# extra arguments for clang
extra_arguments = %(android_headers)s %(clang_headers)s %(cxxgenerator_headers)s %(cocos_headers)s %(android_flags)s %(clang_flags)s %(cocos_flags)s %(extra_flags)s
# what headers to parse
headers = %(cocosdir)s/../runtime-src/Classes/TestJSB.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 = TestJSB
# what should we skip? in the format ClassName::[function function]
# ClassName is a regular expression,but will be used like this: "^ClassName$" functions are also
# regular expressions,they will not be surrounded by "^$". If you want to skip a whole class,just
# add a single "*" as functions. See bellow for several examples. A special class name is "*",which
# will apply to all class names. This is a convenience wildcard to be able to skip similar named
# functions from all classes.
skip =
rename_functions =
rename_classes =
# 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 =
# base classes which will be skipped when their sub-classes found them.
base_classes_to_skip =
# classes that create no constructor
# Set is special and we will use a hand-written constructor
abstract_classes =
# Determining whether to use script object(js object) to control the lifecycle of native(cpp) object or the other way around. Supported values are 'yes' or 'no'.
script_control_cpp = no
TestJSB.h
TestJSB.cpp
- 代码:
//TestJSB.h
// TestJSB.hpp
// TestCocosJs
//
// Created by kaitiren on 16/8/4.
//
//
#ifndef TestJSB_hpp
#define TestJSB_hpp
#include <stdio.h>
#include "cocos2d.h"
using namespace cocos2d;
class TestJSB : public cocos2d::Layer
{
public:
TestJSB();
~TestJSB();
void testprint(void);
void testString(const char* _str);
void testInt(int value);
void testLong(long value);
void testBool(bool isBoo);
CREATE_FUNC(TestJSB);
};
#endif /* TestJSB_h */
///TestJSB.cpp
//
// TestJSB.cpp
// TestCocosJs
//
// Created by kaitiren on 16/8/4.
//
#include "TestJSB.h"
TestJSB:: TestJSB()
{
printf("\n TestJSB:: TestJSB() \n");
}
TestJSB:: ~TestJSB()
{
}
void TestJSB:: testprint(void)
{
CCLOG("TestJSB:: testprint(void)");
printf("\n TestJSB:: testprint(void) \n");
}
void TestJSB:: testString(const char* _str)
{
printf("\n TestJSB:: testString(_str): %s \n",_str);
}
void TestJSB:: testInt(int value)
{
printf("\n TestJSB:: testInt: %d \n ",value);
}
void TestJSB:: testLong(long value)
{
printf("\n TestJSB:: testLong: %ld \n ",value);
}
void TestJSB:: testBool(bool isBoo)
{
printf("\n TestJSB:: testBool: %d \n",isBoo);
}
/// cpp
9. 编译pythongenbindings.py 文件,查看错误部分,并且修改,完成后进行添加到xcode工程(注意: 在cocos2d_js_bindings.xcodeproj项目下的auto 文件加进行添加,这里有一个坑是必须要添加到ios项目内,否则识别不到);
注意导入头文件部分:#include"../../../../../runtime-src/Classes/TestJSB.h"
cmd_args = {
#'cocos2dx.ini': ('cocos2d-x','jsb_cocos2dx_auto'),
#'cocos2dx_audioengine.ini': ('cocos2dx_audioengine','jsb_cocos2dx_audioengine_auto'),
#'cocos2dx_extension.ini': ('cocos2dx_extension','jsb_cocos2dx_extension_auto'),
#'cocos2dx_builder.ini': ('cocos2dx_builder','jsb_cocos2dx_builder_auto'),
#'cocos2dx_ui.ini': ('cocos2dx_ui','jsb_cocos2dx_ui_auto'),
#'cocos2dx_studio.ini': ('cocos2dx_studio','jsb_cocos2dx_studio_auto'),
#'cocos2dx_spine.ini': ('cocos2dx_spine','jsb_cocos2dx_spine_auto'),
#'cocos2dx_3d.ini': ('cocos2dx_3d','jsb_cocos2dx_3d_auto'),
#'cocos2dx_3d_ext.ini': ('cocos2dx_3d_extension','jsb_cocos2dx_3d_extension_auto'),
#'cocos2dx_experimental_webView.ini': ('cocos2dx_experimental_webView','jsb_cocos2dx_experimental_webView_auto'),
#'cocos2dx_experimental_video.ini': ('cocos2dx_experimental_video','jsb_cocos2dx_experimental_video_auto'),
#'cocos2dx_physics3d.ini': ('cocos2dx_physics3d','jsb_cocos2dx_physics3d_auto'),
'cocos2dx_navmesh.ini': ('cocos2dx_navmesh','jsb_cocos2dx_navmesh_auto'),
#################################################
'TestJSB.ini': ('TestJSB','jsb_testjsb_auto'),
'JSBindingIOSWXManager.ini': ('JSBindingIOSWXManager','jsbinding_ioswxmanager_auto'),#添加部分
}
10. 进入当前项目的Classes中的AppDelegate.cpp:
添加:"scripting/js-bindings/auto/jsb_testjsb_auto.hpp"
注册代码: sc->addRegisterCallback(register_all_TestJSB); 这里可以从jsb_testjsb_auto.hpp 中查找;
完成后进行xcode build操作;
11. 进行js代码编辑与测试: (进入 app.js HelloWorldScene)
var HelloWorldScene = cc.Scene.extend({
onEnter:function () {
this._super();
var layer = new HelloWorldLayer();
this.addChild(layer);
///
console.log("aaaaaaaassssssss");
///
var testJSB = new my.TestJSB();
testJSB.testprint();
testJSB.testString("pppppppppppppppppppppppp");
testJSB.testInt(123);
testJSB.testLong(999999999999);
testJSB.testBool(true);
}
});
12. 解决c++ 调用 js 部分: (进入jsb_testjsb_auto.cpp文件夹)
c++ 模块:
bool js_TestJSB_TestJSB_testString(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);
TestJSB* cobj = (TestJSB *)(proxy ? proxy->ptr : NULL);
JSB_PRECONDITION2( cobj,cx,false,"js_TestJSB_TestJSB_testString : Invalid Native Object");
if (argc == 1) {
const char* arg0 = nullptr;
std::string arg0_tmp; ok &= jsval_to_std_string(cx,args.get(0),&arg0_tmp); arg0 = arg0_tmp.c_str();
JSB_PRECONDITION2(ok,"js_TestJSB_TestJSB_testString : Error processing arguments");
cobj->testString(arg0);
args.rval().setUndefined();
/// c++ 调用 js 部分
JSContext* jc = ScriptingCore::getInstance()->getGlobalContext();
// jsval ret;
ScriptingCore::getInstance()->evalString( "cpp_callback(5,100)" ); // js 全局方法
/// c++ 调用 js 部分
/// ScriptingCore::getInstance()->executeFunctionWithOwner(<#jsval owner#>,<#const char *name#>,<#uint32_t argc#>,<#jsval *vp#>) // 此方法可调用全局文件
return true;
}
JS_ReportError(cx,"js_TestJSB_TestJSB_testString : wrong number of arguments: %d,was expecting %d",argc,1);
return false;
}
js 模块:
function cpp_callback(a,b) { cc.log("cpp return two integer: " + a + " " b "ssssssssssssssssssssssssssssssssss"); }
模拟器与移动端运行正常打印;
13. 区分native与web:
if(cc.sys.isNative) { "platform is native !!!"); var testJSB = new my.TestJSB(); testJSB.testprint(); testString("pppppppppppppppppppppppp"); testInt(123); testLong(999999999999); testBool(true); } else { "sys.platform is browser !!!"); }
js binding 部分完结;
14. android版本编译部分;
编译android到当前项目下的proj.android中
控制台执行:
cocos compile -p android
如果有jsb的部分要修改android.mk两处:
- 第一处是在当前项目下runtime-src中的proj.android,导入classes文件夹下的cpp文件到android.mk中;
- 第二处是在/cocos2d-x/cocos/scripting/js-bindings/proj.android/Android.mk进行binding.cpp文件添加;
完成后接续ndk编译尝试;
15. 疑难错误解答:
error: JS: assets/src/app.js:36:ReferenceError: my is not defined
查看AppDelegate.cpp是否没有注册要jsb的cpp函数;
如: sc->addRegisterCallback(register_all_JSBindingIOSWXManager);
error: cpp调用js方法传参问题: (这里可以放到任何一个cpp内:)
#include"scripting/js-bindings/manual/cocos2d_specifics.hpp"
"jsapi.h"
"jsfriendapi.h"
- boolTSScriptJS::RunFunction(std::stringfunName,std::stringarg)
- {
- std::stringrStr=funName+"(\""+arg+"\");"; // 注意这里的括号部分
- jsvalv1;
- JSBoolr=ScriptingCore::getInstance()->evalString(rStr.c_str(),&v1);
- returnr;
}
例子: c++:
JSC 进行cocos js代码加密:
ter: cocos jscompile -s /Users/fox/Documents/js -d /Users/fox/Documents/jsc
-s:js文件路径
-d:jsc输出路径
拷贝项目内的js原文件夹:
js文件路径:
/Users/xxx/xxx/ClientC2DJs/src
/Users/xxx/xxx/ClientC2DJs/frameworks/cocos2d-x/cocos/scripting/js-bindings/script
执行代码:
cocos jscompile -s /Users/fox/Documents/js -d /Users/fox/Documents/jsc
完成后替换项目中的两个文件夹: ...cocos2d/jsbinding/script 不要替换jsbinding中的auto文件夹,...逻辑部分src 但是不要替换main;
完成后运行测试;