cocos2dx在3.x版本后,对物理引擎chipmunk进行了封装,方便了需要物理碰撞支持的开发,
目前的物理碰撞编辑器,比较方便常用的有
physics editor(PE)
https://www.codeandweb.com/physicseditor/
该编辑器win版本,目前还没有找到破解版的,下载的官方版本,可以免费用,但是导出shape有限制。
另一个编辑器是
physic body editor
https://code.google.com/p/box2d-editor/
这个是免费的,但是需要翻墙,你懂的。
打开physic body editor
本文分析的代码,以及physic body editor基本使用教程,请参考
http://cn.cocos2d-x.org/tutorial/show?id=1249
本编辑器导出的是文件格式是json, 首先来看看json格式:
http://www.360doc.com/content/13/0805/16/8074294_304918276.shtml
简单来说,json文件里,{key:value,...} 代表一个对象,里面key是属性,value是属性值,[key:value...] 代表一个数组,两者组合可以表现丰富的信息。
首先我们来看看导出文件的格式
用文字来描述的话,就是根上是一个对象,有一个rigidBodies属性,它里面是一个数组,就是说可以有多个刚体数据,体现在编辑器里:
刚体数据是一个对象,里面有若干属性:
name:刚体名称
imagePath:刚体参考的图片路径,相对路径
origin:原点位置,就是编辑器左下角那个十字坐标,该属性是一个对象
polygons:这是一个二维数组,单元是对象。对象是凸多边形数据,
编辑器可以自动检测出凹多边形,已经孔洞,自动分裂成凸多边形以及三角形。
circles:还没研究
shapes:是一个数组,数组元素是一个对象,看数据是上面polygons用的是所有的点数据。
dynamicObjects:暂时还没有开放
该结构的解析代码:
PhysicsBody* MyBodyParser::bodyFormJson(cocos2d::Node *pNode, const std::string& name)
{
PhysicsBody* body = nullptr;
rapidjson::Value &bodies = doc["rigidBodies"];
if (bodies.IsArray())
{
//遍历文件中的所有body
for (int i=0; i<bodies.Size(); ++i)
{
//找到了请求的那一个
if (0 == strcmp(name.c_str(), bodies[i]["name"].GetString()))
{
rapidjson::Value &bd = bodies[i];
if (bd.IsObject())
{
//创建一个PhysicsBody, 并且根据node的大小来设置
body = PhysicsBody::create();
float width = pNode->getContentSize().width;
//因为编辑器里的比例数据是以原点(左下角)为基准的,所以各shape的点数据需要修正,
float offx = - pNode->getAnchorPoint().x*pNode->getContentSize().width;
float offy = - pNode->getAnchorPoint().y*pNode->getContentSize().height;
Point origin( bd["origin"]["x"].GetDouble(), bd["origin"]["y"].GetDouble());
rapidjson::Value &polygons = bd["polygons"];
for (int i = 0; i<polygons.Size(); ++i)
{
int pcount = polygons[i].Size();
Point* points = new Point[pcount];
for (int pi = 0; pi<pcount; ++pi)
{
// 修正的计算方法 pos - (w/2,h/2),关于为啥y坐标值,是用的width而不是height,因为编辑器里,x、y坐标轴都是同长的,而且是以width为基准,你仔细看json文件,shape的点数据,y值有超过1的,
points[pi].x = offx + width * polygons[i][pcount-1-pi]["x"].GetDouble();
points[pi].y = offy + width * polygons[i][pcount-1-pi]["y"].GetDouble();
}
body->addShape(PhysicsShapePolygon::create(points, pcount, PHYSICSBODY_MATERIAL_DEFAULT));
delete [] points;
}
}
else
{
CCLOG("body: %s not found!", name.c_str());
}
break;
}
}
}
return body;
}
完整代码,可以从以下网址下载
https://github.com/xhcnb/accurate_hit_testing_cocos2d_x_3_0