http://blog.chukong-inc.com/index.php/2012/11/07/关于调用spii引擎注册的js函数的警示/
一个小小的返回值问题又引发了一场耗时的BUG大搜索悲剧。希望看过这篇文章的同学不会再发生诸如此类的悲剧了。
先来看一段简单的代码
// 获取玩家在地图块中的索引位置
var startPoint = m_mapCom.getTileIndexInLayer(“collider”, self.player.x, self.player.y);
print(“playerX:” + startPoint.x + “playerY:” + startPoint.y);
// 获取目的点在地图块中的的索引位置
var endPoint = m_mapCom.getTileIndexInLayer(“collider”, self.curPos.x, self.curPos.y);
print(“endPointX:” + endPoint.x + print(“endPointY:” + endPoint.y);
代码很简单,为了寻路获取玩家当前位置和寻路点。结果打印出来的位置很正常。但是传入startPoint和endPoint寻路时返回的路径怎么都只找到最后的一个路径点(路径数组长度始终为1)。刚开始还怀疑寻路算法有问题。经过一系列的排错侯发现寻路中传入的两个点坐标的位置完全一样。难道startPoint和endPoint真是一个对象?事实确实如此,改下代码就真相大白了。
// 获取玩家在地图块中的索引位置
var startPoint = m_mapCom.getTileIndexInLayer(“collider”, self.player.x, self.player.y);
// 获取目的点在地图块中的的索引位置
var endPoint = m_mapCom.getTileIndexInLayer(“collider”, self.curPos.x, self.curPos.y);
print(“playerX:” + startPoint.x + “playerY:” + startPoint.y);
print(“endPointX:” + endPoint.x + print(“endPointY:” + endPoint.y);
当把两个print连续执行时发现player坐标和endPoint完全一致。问题出在getTileIndexInLayer函数。此为GameMap类的一个导出接口,返回的是一个GLKVector4
指针,注意,是指针。源码实现中返回的是一个类成员变量。也就是意味着每次返回的都是同一个对象,只是对象里的内容变化了。这种写法可以理解,源于语言的差异,如果返回一个堆中new出的对象,那么如何管理这个返回值对象的回收是个问题。通过查看SpiderMonkey的API文档了解到SpiderMonkey中可以通过JS_NewObject来创建一个C++端的JS对象(JS_NewObject),文档参考如下。
https://developer.mozilla.org/en-US/docs/SpiderMonkey/JSAPI_Reference/JS_NewObject
以我以前对Lua脚本的经验,我个人做一个大胆的假设,应该可以尝试使用这个JS_NewObject作为返回值,因为这个对象的内存管理属于SpiderMonkey引擎的工作,我们不需要关心。另外可以动态的往里面填属性,使用JS_DefineObject函数,在此例中可以用来填充X,Y坐标作为返回值。目前只是假设,但是我基本可以确定一定有办法可以解决这个问题。找时间验证吧~大家有兴趣可以先试试^^