Cocos Creator JSB [Lv.1]
Posted VermillionTear
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Cocos Creator JSB [Lv.1] 相关的知识,希望对你有一定的参考价值。
摘要
本系列文章主要实操JSB
的手动绑定,在官方教程的基础上,做了适当的修改,并增加了新的内容。
文中对相关知识点进行适当展开,不做深入研究。
以实际操作做为出发点,帮助读者快速实现并且掌握JSB
手动绑定。
系列文章
JSB能做什么
他能让js
脚本与C++
互相传递参数,互相调用函数。他搭建了js
脚本与C++
之间通讯的桥梁。
环境
- Cocos Creator 2.4.4
- Visual Studio Community 2017
资源
准备工作
- 一张小姐姐的图片。没错!你没有看错,就是一张小姐姐的图片,我们要通过
JSB
跟小姐姐互动起来~ - 一张心形的图片。
- 创建Empty工程。
- 构建工程,
模板一定要选default
,因为这样才会将cocos2dx
的源码拷贝到发布路径
下。我们需要修改cocos2dx
的部分源码,从而实现JSB
绑定。
窗口大小调整为Cocos Creator
中Canvas
节点设置的设计分辨率
大小。
构建完成后,在发布路径
会看到jsb-default
目录。
cocos2dx
源码目录为发布路径/jsb-default/frameworks/cocos2d-x/
。之后为了叙述方便,提及cocos2dx
源码中的文件,如不做特殊说明,均以此目录作为根目录。
正式开始
对工程做一些修改
资源管理器
层级管理器
- 对节点的层级稍稍做了规范化,保证UI与代码分开,代码均挂载在Controller下对应的节点上。
- 创建
JSBController.js
脚本,并且挂载在JSBController
节点上。
之后节点相关的设置请参考工程中的设置,文中不再赘述。
场景编辑器
如何互动
这回小姐姐一下子就出现在我们面前了,可是怎么跟她互动呢?
我们模拟小姐姐在C++
层面,而我们在js
层面。通过JSB
搭建的桥梁,实现参数的相互传递,以及函数的相互调用。
小姐姐现身
我们在C++
层面创建一个小姐姐的类。
在cocos
目录下创建myjsb
目录,并在其中创建Goddess.h
和Goddess.cpp
。
Goddess.h
#ifndef __CC_GODDESS_H__
#define __CC_GODDESS_H__
#include <string>
#include "base/ccMacros.h"
namespace cocos2d { namespace myjsb { // 命名空间,cocos2d::myjsb
class CC_DLL Goddess // 单例类
{
public:
static Goddess* getInstance(); // 获取单例
static void destroyInstance(); // 销毁单例
protected:
static Goddess* _instance; // 实例
};
}} // namespace cocos2d::myjsb
#endif // __CC_GODDESS_H__
Goddess.cpp
#include "myjsb/Goddess.h"
namespace cocos2d { namespace myjsb {
Goddess* Goddess::_instance = nullptr; // 必须写,否则报错“无法解析的外部符号”。
// 获取单例。
Goddess* Goddess::getInstance()
{
if (_instance == nullptr)
{
_instance = new Goddess();
}
return _instance;
}
// 销毁单例。
void Goddess::destroyInstance()
{
CC_SAFE_DELETE(_instance);
}
}} // namespace cocos2d::myjsb
将这两个文件加入libcocos2d
中,从而让它们编译进libcocos2d
库中,
与小姐姐互动的桥梁
在cocos/scripting/js-bindings/auto
目录下创建jsb_cocos2dx_myjsb_auto.hpp
和jsb_cocos2dx_myjsb_auto.cpp
。
jsb_cocos2dx_myjsb_auto.hpp
#pragma once
#include "base/ccConfig.h"
#if (CC_TARGET_PLATFORM == CC_PLATFORM_android || CC_TARGET_PLATFORM == CC_PLATFORM_ios || CC_TARGET_PLATFORM == CC_PLATFORM_MAC || CC_TARGET_PLATFORM == CC_PLATFORM_WIN32)
#include "cocos/scripting/js-bindings/jswrapper/SeApi.h"
extern se::Object* __jsb_cocos2d_myjsb_Goddess_proto;
extern se::Class* __jsb_cocos2d_myjsb_Goddess_class;
bool js_register_cocos2d_myjsb_Goddess(se::Object* obj);
bool register_all_myjsb(se::Object* obj);
// 声明作为桥梁的函数。
// 桥梁函数的作用:
// 1、将js层面传递过来的参数从se::Value类型转换为C++的类型。
// 2、调用对应的(在js_register_xxx中绑定的)C++类的成员函数,并传递转换后的的参数。
// 3、得到返回值,并将其转换为se::Value类型。
// 4、存入s.rval中,s.rval中的值就是返回给js层面的返回值。
SE_DECLARE_FUNC(js_cocos2d_myjsb_Goddess_getInstance);
#endif //#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID || CC_TARGET_PLATFORM == CC_PLATFORM_IOS || CC_TARGET_PLATFORM == CC_PLATFORM_MAC || CC_TARGET_PLATFORM == CC_PLATFORM_WIN32)
jsb_cocos2dx_myjsb_auto.cpp
#include "scripting/js-bindings/auto/jsb_cocos2dx_myjsb_auto.hpp"
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID || CC_TARGET_PLATFORM == CC_PLATFORM_IOS || CC_TARGET_PLATFORM == CC_PLATFORM_MAC || CC_TARGET_PLATFORM == CC_PLATFORM_WIN32)
#include "scripting/js-bindings/manual/jsb_conversions.hpp"
#include "scripting/js-bindings/manual/jsb_global.h"
#include "myjsb/Goddess.h"
se::Object* __jsb_cocos2d_myjsb_Goddess_proto = nullptr;
se::Class* __jsb_cocos2d_myjsb_Goddess_class = nullptr;
// 桥梁函数,jsb.Goddess.getInstance()实际会调用到这里。
static bool js_cocos2d_myjsb_Goddess_getInstance(se::State &s) {
const auto& args = s.args(); // 传递的参数。
size_t argc = args.size(); // 参数的数量。
CC_UNUSED bool ok = true; // 参数转换是否成功的标志。
if (argc == 0) { // 需要0个参数。
// 不需要参数,也就没有了参数的转换部分。
cocos2d::myjsb::Goddess* result = cocos2d::myjsb::Goddess::getInstance(); // 获取Goddess类的实例。
// 将Goddess类的实例转换为se::Value,并赋值到s.rval。s.rval中的值就是返回给js层面的返回值。
ok &= native_ptr_to_seval<cocos2d::myjsb::Goddess>((cocos2d::myjsb::Goddess*)result, &s.rval());
SE_PRECONDITION2(ok, false, "js_cocos2d_myjsb_Goddess_getInstance : Error processing arguments");
return true;
}
// 传递的参数不正确时,打印的提示信息。
SE_REPORT_ERROR("wrong number of arguments: %d, was expecting %d", (int)argc, 0);
return false;
}
SE_BIND_FUNC(js_cocos2d_myjsb_Goddess_getInstance);
bool js_register_cocos2d_myjsb_Goddess(se::Object* obj) {
auto cls = se::Class::create("Goddess", obj, nullptr, nullptr);
// 这里就是定义,jsb.Goddess 要暴露出一个 getInstance 函数,
// jsb.Goddess.getInstance() 时,在 JSB 中要调用 js_cocos2d_myjsb_Goddess_getInstance
cls->defineStaticFunction("getInstance", _SE(js_cocos2d_myjsb_Goddess_getInstance));
cls->install();
// 将 se::Class::create 的 Goddess 与 C++ 实际的 Goddess 类对应起来。
JSBClassType::registerClass<cocos2d::myjsb::Goddess>(cls);
__jsb_cocos2d_myjsb_Goddess_proto = cls->getProto();
__jsb_cocos2d_myjsb_Goddess_class = cls;
se::ScriptEngine::getInstance()->clearException();
return true;
}
bool register_all_myjsb(se::Object* obj)
{
// Get the ns
se::Value nsVal;
if (!obj->getProperty("jsb", &nsVal))
{
se::HandleObject jsobj(se::Object::createPlainObject());
nsVal.setObject(jsobj);
obj->setProperty("jsb", nsVal);
}
se::Object* ns = nsVal.toObject();
// 以下函数被调用之后,jsb.Goddess就可以使用了。
js_register_cocos2d_myjsb_Goddess(ns);
return true;
}
#endif //#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID || CC_TARGET_PLATFORM == CC_PLATFORM_IOS || CC_TARGET_PLATFORM == CC_PLATFORM_MAC || CC_TARGET_PLATFORM == CC_PLATFORM_WIN32)
将这两个文件加入libcocos2d
中,从而让它们编译进libcocos2d
库中,
由于myjsb
是新增加的模块,所以需要在发布路径/jsb-default/frameworks/runtime-src/Classes/jsb_module_register.cpp
中增加myjsb
的注册逻辑,实际上就是调用register_all_myjsb
。
注意cocos/scripting/js-bindings/manual/
目录下也有一个jsb_module_register.cpp
,不要使用这个,
而是要使用发布路径/jsb-default/frameworks/runtime-src/Classes/
目录下的。
jsb_module_register.cpp
...
#include "cocos/scripting/js-bindings/auto/jsb_cocos2dx_myjsb_auto.hpp"
...
se->addRegisterCallback(register_all_myjsb);
...
找到小姐姐
经过上述工作,我们在js
层面就可以获取到小姐姐的实例了,
JSBController.js
let _goddess = null // 小姐姐的实例。
cc.Class({
extends: cc.Component,
properties: {
// TODO
},
onLoad () {
_goddess = jsb.Goddess.getInstance() // 获取小姐姐的实例。
},
});
划重点
- 构建工程时,
模板
要选择default
。 JSB手动绑定
的一般流程:cocos/myjsb/
下定义类,cocos/scripting/js-bindings/auto/
下定义桥梁,发布路径/jsb-default/frameworks/runtime-src/Classes/jsb_module_register.cpp
中注册桥梁。- 注意
jsb_module_register.cpp
的目录。 - 绑定单例类的写法。
以上是关于Cocos Creator JSB [Lv.1] 的主要内容,如果未能解决你的问题,请参考以下文章