- 本帖最后由 zjf_to@126.com 于 2012-12-27 10:51 编辑 *
这几天公司要把一款以前用cocos2d(object-c)版本的游戏翻译成可以跨平台的,我个人是想要用C++的,因为我对C++还是有点经验的,但是没理法,才刚毕业,老板不是很相信,很是怀疑我的C++能力,在加上公司只有我一个懂C++,于是,他问了另外一个做服务端的,用PHP写的,基本上他只会PHP的,然后他说用JS来,说JS的开发效率高。本来我是比较担心JS的心能,但是他发了三天时间,终于把-x里面的jsdemo下到安卓上面,然后说js的性能应该没有问题,但是我对其还是比较怀疑的。看了一下-x,后来发现,-x里面的jsbinding里面调用的还是原生的C++,也就是说渲染引擎跟C++其实应该是一样的,性能应该跟原生的效率不会差很多,个人理解。那就只能用JS了,发了点牢骚,进入正题
在手机上面,-x通过jsbingding,将C++的源生库给绑定成JS可以直接调用的方式。但是基本看不到关于将C++绑定成JS的相关资料,而且后来2.0加上去的一些扩展类都没有做相应的绑定。既然上头说要用JS开发,那这些控件肯定是要绑定的。所以这个事情就落到了我的头上了。
既然没有相关的资料,没有理法,只能看源代码,参考着绑定。刚开始做这个的时候,我决定从CCTableView开始入手,因为个人感觉这个东西涉及到的应该会比较全面,有JS调用C++和C++调用JS,如果这个可以绑定成功了,后面的应该都没有什么问题了吧。开始的时候,可以先看一下cocos2d_specifics.cpp 、cocos2dx.cpp这两个文件,只要照着这个上面的方式做,一些简单的方法绑定应该都没有太大的问题,核心是ibjs_static.a这个静态库,有点大,>20M,按照这两个文件的写法,封装好要传递的参数和要要调用的函数,基本上不会有很大的问题,浪费时间,体力活。开始CCTableView的绑定。一开始我自己是这样认为的。首先我们在JS创建一个CCTableView的控件,比如要用到Create方法,也就是JS要调用C++的代码,这个的绑定方法很简单,参考下cocos2d_specifics.cpp 、cocos2dx.cpp的方式写一个,可以发现C++的Create被调用到了,而且JS也到了一个CCTableView的对象了(JS上面用的对象),创建成功之后,CCTableView的三个调用数据源的委托方法要被实现,也就是说我们要在JS上面重写这些委托方法,然后C++去调用JS的方法。这时,我发现这个方式就是跟touch事件的处理有点相似了,接着看CCLayer
bool CCLayer::ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent)
{
if (kScriptTypeNone != m_eScriptType)
{
return excuteScriptTouchHandler(CCTOUCHBEGAN, pTouch) == 0 ? false : true;
}
CC_UNUSED_PARAM(pTouch);
CC_UNUSED_PARAM(pEvent);
CCAssert(false, "Layer#ccTouchBegan override me");
return true;
}
这边我们可以看到,如果是lua或者js脚本的时候,会去执行一个方法,这个方法可以让C++调用到JS,跟踪后我们发现最终在ScriptingCore.cpp这个文件里面发现了调用JS的方法,int ScriptingCore::executeLayerTouchEvent(CCLayer* pLayer, int eventType, CCTouch *pTouch);所以这个在这个tableview里面我们是不是也要弄个分支,让他去执行一个可以让C++调到js的方法呢。但是在CCTableView.cpp里面,我们发现这些委托方法被调用的地方有很多,这样要写分支的地方也就会很多,这样一来代码的维护就会出现问题,没理法,只能把CCTableView在往上面封装一层,这边我把他给封装成了JSTableView的样子
JSTableView.h
//
// JSTableView.h
// tableview
//
// Created by mac on 12-12-25.
//
//
#ifndef __tableview__JSTableView__
#define __tableview__JSTableView__
#include "cocos2d.h"
#include "CCTableView.h"
#include "CCTableViewCell.h"
USING_NS_CC;
USING_NS_CC_EXT;
NS_CC_EXT_BEGIN
class JSTableView;
class JSTableViewDelegate
{
public:
virtual void executeTableCellTouched(JSTableView* table, CCTableViewCell* cell) = 0;
};
class JSTableViewDataSource
{
public:
virtual CCSize executeCellSizeForTable(JSTableView *table) = 0;
virtual CCTableViewCell* executeTableCellAtIndex(JSTableView *table, unsigned int idx) = 0;
virtual unsigned int executeNumberOfCellsInTableView(JSTableView *table) = 0;
};
class JSTableView:public CCTableView,public CCTableViewDataSource,public CCTableViewDelegate
{
public:
JSTableView()
{
CCTableView::setDataSource(this);
}
static JSTableView* create(JSTableViewDataSource* dataSource, CCSize size,CCNode *container = NULL)
{
JSTableView *table = new JSTableView();
table->initWithViewSize(size, container);
table->autorelease();
table->setDataSource(dataSource);
table->_updateContentSize();
return table;
}
virtual void scrollViewDidScroll(cocos2d::extension::CCScrollView* view)
{
CCTableView::scrollViewDidScroll(view);
}
virtual void scrollViewDidZoom(cocos2d::extension::CCScrollView* view)
{
CCTableView::scrollViewDidZoom(view);
}
virtual void tableCellTouched(CCTableView* table, CCTableViewCell* cell);
virtual CCSize cellSizeForTable(CCTableView *table);
virtual CCTableViewCell* tableCellAtIndex(CCTableView *table, unsigned int idx);
virtual unsigned int numberOfCellsInTableView(CCTableView *table);
inline void setDelegate(JSTableViewDelegate* p)
{
CCTableView::setDelegate(this);
m_pJSTableViewDelegate = p;
}
inline void setDataSource(JSTableViewDataSource* p)
{
CCTableView::setDataSource(this);
m_pJSTableViewDataSource = p;
}
private:
JSTableViewDataSource *m_pJSTableViewDataSource;
JSTableViewDelegate *m_pJSTableViewDelegate;
};
NS_CC_EXT_END
#endif /* defined(__tableview__JSTableView__) */
JSTableView.cpp
//
// JSTableView.cpp
// tableview
//
// Created by mac on 12-12-25.
//
//
#include "JSTableView.h"
NS_CC_EXT_BEGIN
void JSTableView::tableCellTouched(CCTableView* table, CCTableViewCell* cell)
{
if (m_pJSTableViewDelegate)
{
CCScriptEngineManager::sharedManager()->getScriptEngine()->executeTableCellTouch((JSTableViewDelegate*)m_pJSTableViewDelegate, this, cell);
}
}
CCSize JSTableView::cellSizeForTable(CCTableView *table)
{
if (m_pJSTableViewDataSource)
{
return CCScriptEngineManager::sharedManager()->getScriptEngine()->executeCellSizeForTable(m_pJSTableViewDataSource, this);
}
return CCSizeZero;
}
CCTableViewCell* JSTableView::tableCellAtIndex(CCTableView *table, unsigned int idx)
{
if (m_pJSTableViewDataSource)
{
return CCScriptEngineManager::sharedManager()->getScriptEngine()->executeTableCellAtIndex(m_pJSTableViewDataSource, this, idx);
}
return NULL;
}
unsigned int JSTableView::numberOfCellsInTableView(CCTableView *table)
{
if (m_pJSTableViewDataSource)
{
return CCScriptEngineManager::sharedManager()->getScriptEngine()->executeNumberOfCellsInTableView(m_pJSTableViewDataSource, this);
}
return 0;
}
NS_CC_EXT_END
这样一来省去了要去CCTableView查找每个委托被调用到的地方,然后在添加调用JS的方法
ScriptingCore.cpp 添加方法
unsigned int ScriptingCore::executeNumberOfCellsInTableView(JSTableViewDataSource *dest,JSTableView *table)
{
std::string funcName = "numberOfCellsInTableView";
js_proxy_t * p;
JS_GET_PROXY(p, dest);
if (!p) return NULL;
jsval value1;
js_proxy_t * p1;
p1 = js_get_or_create_proxy<cocos2d::extension::JSTableView>(this->getGlobalContext(),table);
value1 = OBJECT_TO_JSVAL(p1->obj);
jsval *date = new jsval();
date = value1;
jsval retval;
executeJSFunctionWithName(this->cx_, p->obj, funcName.c_str(), *date, retval,1);
return JSVAL_TO_INT(retval);
}
现在,基本上就可以把CCTableView的库给绑定成功了。主要核心是那个20多兆的库,只要参考着-x已有的绑定方法和CCTableView的绑定方式,构建好要传递的参数和方法,后面的绑定应该不会有很大的问题了
不想在写绑定过程遇到的问题了,还要苦逼的上班呢。直接上代码,希望交流,我也是刚开始做的,有错的留言
源代码就:http://download.csdn.net/detail/zjf526655060/4932847