cocos2d-x 3.7.1 js中集成ActionInterval

本人需求,我们项目前期是做h5版本,但是目前要转app,所以要测试jsb.发现下面这个问题
http://discuss.cocos2d-x.org/t/cocos2d-js-beta-jsb-android-project-cc-actioninterval-extend-is-not-function/15380
这种情况两种解决办法1:游戏中用到的,换一种实现方式,显然不是很合适,! 2:改jsb层代码!
本人当然采用第二种实现方式
具体改法如下
jsb_cocos2dx_auto 中添加jsb构造接口
bool js_cocos2dx_ActionInterval_constructor(JSContext *cx, uint32_t argc, jsval vp){
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
bool ok = true;
cocos2d::ActionInterval
cobj = new (std::nothrow) cocos2d::ActionInterval();
cocos2d::Ref *_ccobj = dynamic_cast<cocos2d::Ref *>(cobj);
if (_ccobj) {
_ccobj->autorelease();
}
TypeTestcocos2d::ActionInterval t;
js_type_class_t *typeClass = nullptr;
std::string typeName = t.s_name();
auto typeMapIter = _js_global_type_map.find(typeName);
CCASSERT(typeMapIter != _js_global_type_map.end(), “Can’t find the class type!”);
typeClass = typeMapIter->second;
CCASSERT(typeClass, “The value is null.”);
// JSObject obj = JS_NewObject(cx, typeClass->jsclass, typeClass->proto, typeClass->parentProto);
JS::RootedObject proto(cx, typeClass->proto.get());
JS::RootedObject parent(cx, typeClass->parentProto.get());
JS::RootedObject obj(cx, JS_NewObject(cx, typeClass->jsclass, proto, parent));
args.rval().set(OBJECT_TO_JSVAL(obj));
// link the native object with the javascript object
js_proxy_t
p = jsb_new_proxy(cobj, obj);
AddNamedObjectRoot(cx, &p->obj, “cocos2d::ActionInterval”);
if (JS_HasProperty(cx, obj, “_ctor”, &ok) && ok)
ScriptingCore::getInstance()->executeFunctionWithOwner(OBJECT_TO_JSVAL(obj), “_ctor”, args);
return true;
}

在注册jsb接口中作如下更改
void js_register_cocos2dx_ActionInterval(JSContext *cx, JS::HandleObject global) {
jsb_cocos2d_ActionInterval_class = (JSClass *)calloc(1, sizeof(JSClass));
jsb_cocos2d_ActionInterval_class->name = “ActionInterval”;
jsb_cocos2d_ActionInterval_class->addProperty = JS_PropertyStub;
jsb_cocos2d_ActionInterval_class->delProperty = JS_DeletePropertyStub;
jsb_cocos2d_ActionInterval_class->getProperty = JS_PropertyStub;
jsb_cocos2d_ActionInterval_class->setProperty = JS_StrictPropertyStub;
jsb_cocos2d_ActionInterval_class->enumerate = JS_EnumerateStub;
jsb_cocos2d_ActionInterval_class->resolve = JS_ResolveStub;
jsb_cocos2d_ActionInterval_class->convert = JS_ConvertStub;
jsb_cocos2d_ActionInterval_class->finalize = js_cocos2d_ActionInterval_finalize;
jsb_cocos2d_ActionInterval_class->flags = JSCLASS_HAS_RESERVED_SLOTS(2);

		static JSPropertySpec properties[] = {
			JS_PSG("__nativeObj", js_is_native_obj, JSPROP_PERMANENT | JSPROP_ENUMERATE),
			JS_PS_END
		};

		static JSFunctionSpec funcs[] = {
			JS_FN("getAmplitudeRate", js_cocos2dx_ActionInterval_getAmplitudeRate, 0, JSPROP_PERMANENT | JSPROP_ENUMERATE),
			JS_FN("initWithDuration", js_cocos2dx_ActionInterval_initWithDuration, 1, JSPROP_PERMANENT | JSPROP_ENUMERATE),
			JS_FN("setAmplitudeRate", js_cocos2dx_ActionInterval_setAmplitudeRate, 1, JSPROP_PERMANENT | JSPROP_ENUMERATE),
			JS_FN("getElapsed", js_cocos2dx_ActionInterval_getElapsed, 0, JSPROP_PERMANENT | JSPROP_ENUMERATE),
			JS_FS_END
		};

		JSFunctionSpec *st_funcs = NULL;

		jsb_cocos2d_ActionInterval_prototype = JS_InitClass(
			cx, global,
			JS::RootedObject(cx, jsb_cocos2d_FiniteTimeAction_prototype),
			jsb_cocos2d_ActionInterval_class,
			js_cocos2dx_ActionInterval_constructor, 0,
			properties,
			funcs,
			NULL, // no static properties
			st_funcs);
		// make the class enumerable in the registered namespace
	//  bool found;
	//FIXME: Removed in Firefox v27 
	//  JS_SetPropertyAttributes(cx, global, "ActionInterval", JSPROP_ENUMERATE | JSPROP_READONLY, &found);

		// add the proto and JSClass to the type->js info hash table
		TypeTest<cocos2d::ActionInterval> t;
		js_type_class_t *p;
		std::string typeName = t.s_name();
		if (_js_global_type_map.find(typeName) == _js_global_type_map.end())
		{
			p = (js_type_class_t *)malloc(sizeof(js_type_class_t));
			p->jsclass = jsb_cocos2d_ActionInterval_class;
			p->proto = jsb_cocos2d_ActionInterval_prototype;
			p->parentProto = jsb_cocos2d_FiniteTimeAction_prototype;
			_js_global_type_map.insert(std::make_pair(typeName, p));
		}
	}

然后在js层中添加如下代码
if(!cc.ActionInterval.extend) {
cc.ActionInterval.extend = cc.Class.extend;
}

项目中定义ActionInterval子类的方式如下
td.TruntableAction = cc.ActionInterval.extend(/** @lends cc.ScaleTo# */{

_startPos: null,
_endPos: null,
_deltaPos: null,
_poses: null,
_timePassed: null,

/**
 * Constructor function, override it to extend the construction behavior, remember to call "this._super()" in the extended "ctor" function.
 * @param {Number} duration
 * @param {Number} sx  scale parameter in X
 * @param {Number} [sy] scale parameter in Y, if Null equal to sx
 */
ctor:function () {
    cc.ActionInterval.prototype.ctor && cc.ActionInterval.prototype.ctor.call(this,duration); // jsb
    // this._super && this._super(); // js | html5 framework
},

/**
 * Initializes the action.
 * @param {Number} duration
 * @param {Number} sx
 * @param {Number} [sy=]
 * @return {Boolean}
 */
initWithDuration:function (duration, poses, endPos) { //function overload here
    if (poses !== undefined && cc.ActionInterval.prototype.initWithDuration.call(this, duration)) {
        this._timePassed = 0;
        this._endPos = endPos;
        this._poses = poses;
        return true;
    }
    return false;
},

/**
 * returns a new clone of the action
 * @returns {cc.ScaleTo}
 */
clone:function () {
    var action = new td.TruntableAction();
    this._cloneDecoration(action);
    action.initWithDuration(this._duration, this._poses, this._endPos);
    return action;
},

/**
 * Start the action with target.
 * @param {cc.Node} target
 */
startWithTarget:function (target) {
    cc.ActionInterval.prototype.startWithTarget.call(this, target);
    this._timePassed = 0;
    this._startPos = this._computeCurPos();
    // cc.log("start pos is:" + this._startPos);
    var round = this._poses.length;
    var lastRoundSteps;
    if (this._endPos === this._startPos) {
        lastRoundSteps = round;
    } else {
        lastRoundSteps = (round + this._endPos - this._startPos) % round;
    }
    this._deltaPos = 2 * round + lastRoundSteps;
    // cc.log("delta pos is:" + this._deltaPos);
},

_computeCurPos: function() {
    var pos = this.target.getPosition();
    for (var i = 0; i < this._poses.length; i++) {
        var ipos = this._poses[i];
        if (uf.utils.Math.distanceSQ(pos, ipos) <= 4) {
            return i;
        }
    }
    cc.error("pos error");
},

/**
 * Called once per frame. Time is the number of seconds of a frame interval.
 * @param {Number} dt
 */
update:function (dt) {
    dt = this._computeEaseTime(dt);
    if (this.target) {
        var targetPos = this._startPos + Math.floor(this._deltaPos * dt);
        // cc.log("dt: " + dt + ", targetPos:" + targetPos + ", real pos is:" + (targetPos % this._poses.length));
        var position = this._poses[targetPos % this._poses.length];
        this.target.setPosition(position);
    }
}

});

但是,在new 的时候并没有调用js_cocos2dx_ActionInterval_constructor 这个接口导致报如下错误
TurntableActivityHome.js:293:Error: js_cocos2dx_ActionInterval_initWithDuration : Invalid Native Object

还有一种方案就是在c++中实现该动画的自定义,然后到处到js中使用但是,本人对C++不是很熟,所以能导出ActionInterval直接在js中自定义最好!有哪位兄弟比较熟悉还望指教一二!

目前Action这个类并没有绑定,需要做到在js层继承action是有一定工作量的。
比如js层的函数覆盖,目前action类并没有通知给脚本层,脚本层覆盖了startWithTarget,却收不到通知。
这作为一个新需求吧,建议在github上建一个issue作为新版本的新需求。

好的,Thx