本人需求,我们项目前期是做h5版本,但是目前要转app,所以要测试jsb.发现下面这个问题
这种情况两种解决办法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 = dynamiccast(cobj);
if (_ccobj) {
_ccobj->autorelease();
}
TypeTest t;
js_type_class_t *typeClass = nullptr;
std::string typeName = t.s_name();
auto typeMapIter = jsglobal_type_map.find(typeName);
CCASSERT(typeMapIter != jsglobal_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中自定义最好!有哪位兄弟比较熟悉还望指教一二!