下载与安装PhysicsEditor
物理编辑器介绍
1.VertexHelper
免费、开源的物理编辑器,只能在Mac平台下使用。
2.PhysicsEditor
收费,支持windows与mac。可免费使用,有功能限制。
这里使用的是PhysicsEditor。
PhysicsEditor下载地址:
下载地址一:https://www.codeandweb.com/physicseditor
下载地址二:http://pan.baidu.com/s/1mgp8eHa
在PhysicsEditor安装目录下有一个Examples文件夹。这里有各个物理引擎的使用示例。Cocos2d-X文件夹是Cocos2d-x的例子,但是是使用Cocos2d-x1.0。
编辑器的使用
1.点击Add Sprites按钮添加图片,或者直接拖到左边的窗口
2.编辑顶点,编辑之前先在编辑界面顶部选择形状的类型(圆形、多边形),右键添加顶点,用鼠标拖拽顶点,编辑形状。
3.导出格式设置,在Cocos2d-x中使用的是plist格式的文件。所以选择Box2D geneic PLIST
4.相关参数的设置
5.使用魔法棒自动填充顶点。
点击魔法棒后,在弹出的对话框中的Tolerance字段设置顶点的数量因子。数字越小,顶点数量越多;数字越大,顶点数量越少。默认为5,一般已经可以把图形轮廓描绘出来了。
6.点击Publish导出,导出文件记录了图片的夹具定义信息,key为在编辑器中设置的资源名称。
在Cocos2d-x中使用导出文件
开发环境说明:
游戏引擎版本:Cocos2d-x2.2.1
物理引擎:box2d
系统:win7
1.拷贝GB2ShapeCache-x.cpp和GB2ShapeCache-x.h到工程。
对于导出文件的加载和解析方法封装在GB2ShapeCache这个类中。类的定义与实现在PhysicsEditor\Examples\Cocos2d-X\Demo\Demo\generic-box2d-plist目录下的GB2ShapeCache-x.cpp和GB2ShapeCache-x.h文件中。
把这两个文件拷贝到工程Classes目录下。
注意:由于例子工程使用是的Cocos2d-x1.0,使用了过时的api,所以在使用的时候还需要做些修改。
2.替换GB2ShapeCache-x.cpp中使用的废弃api
//
// GB2ShapeCache-x.cpp
//
// Loads physics sprites created with http://www.PhysicsEditor.de
// To be used with cocos2d-x
//
// Generic Shape Cache for box2d
//
// Created by Thomas Broquist
//
// http://www.PhysicsEditor.de
// http://texturepacker.com
// http://www.code-and-web.de
//
// All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
#include "GB2ShapeCache-x.h"
#include "Box2D/Box2D.h"
#include "cocoa/CCNS.h"
using namespace cocos2d;
/**
* Internal class to hold the fixtures
*/
class FixtureDef {
public:
FixtureDef()
: next(NULL) {}
~FixtureDef() {
delete next;
delete fixture.shape;
}
FixtureDef *next;
b2FixtureDef fixture;
int callbackData;
};
class BodyDef {
public:
BodyDef()
: fixtures(NULL) {}
~BodyDef() {
if (fixtures)
delete fixtures;
}
FixtureDef *fixtures;
CCPoint anchorPoint;
};
static GB2ShapeCache *_sharedGB2ShapeCache = NULL;
GB2ShapeCache* GB2ShapeCache::sharedGB2ShapeCache(void) {
if (!_sharedGB2ShapeCache) {
_sharedGB2ShapeCache = new GB2ShapeCache();
_sharedGB2ShapeCache->init();
}
return _sharedGB2ShapeCache;
}
bool GB2ShapeCache::init() {
return true;
}
void GB2ShapeCache::reset() {
std::map
::iterator iter;
for (iter = shapeObjects.begin() ; iter != shapeObjects.end() ; ++iter) {
delete iter->second;
}
shapeObjects.clear();
}
void GB2ShapeCache::addFixturesToBody(b2Body *body, const std::string &shape) {
std::map
::iterator pos = shapeObjects.find(shape);
assert(pos != shapeObjects.end());
BodyDef *so = (*pos).second;
FixtureDef *fix = so->fixtures;
while (fix) {
body->CreateFixture(&fix->fixture);
fix = fix->next;
}
}
cocos2d::CCPoint GB2ShapeCache::anchorPointForShape(const std::string &shape) {
std::map
::iterator pos = shapeObjects.find(shape);
assert(pos != shapeObjects.end());
BodyDef *bd = (*pos).second;
return bd->anchorPoint;
}
void GB2ShapeCache::addShapesWithFile(const std::string &plist) {
//const char *fullName = CCFileUtils::sharedFileUtils()->fullPathForFilename(plist.c_str()).c_str();
CCDictionary *dict = CCDictionary::createWithContentsOfFile(plist.c_str());
// not triggered - cocos2dx delivers empty dict if non was found
CCAssert(dict != NULL, "Shape-file not found");
CCAssert(dict->count() != 0, "plist file empty or not existing");
CCDictionary *metadataDict = (CCDictionary *)dict->objectForKey("metadata");
int format = static_cast
(metadataDict->objectForKey("format"))->intValue();
ptmRatio = static_cast
(metadataDict->objectForKey("ptm_ratio"))->floatValue(); CCLOG("ptmRatio = %f",ptmRatio); CCAssert(format == 1, "Format not supported"); CCDictionary *bodyDict = (CCDictionary *)dict->objectForKey("bodies"); b2Vec2 vertices[b2_maxPolygonVertices]; CCDictElement *dictElem; std::string bodyName; CCDictionary *bodyData; //iterate body list CCDICT_FOREACH(bodyDict,dictElem ) { bodyData = (CCDictionary*)dictElem->getObject(); bodyName = dictElem->getStrKey(); BodyDef *bodyDef = new BodyDef(); bodyDef->anchorPoint = CCPointFromString(static_cast
(bodyData->objectForKey("anchorpoint"))->getCString()); CCArray *fixtureList = (CCArray*)(bodyData->objectForKey("fixtures")); FixtureDef **nextFixtureDef = &(bodyDef->fixtures); //iterate fixture list CCObject *arrayElem; CCARRAY_FOREACH(fixtureList, arrayElem) { b2FixtureDef basicData; CCDictionary* fixtureData = (CCDictionary*)arrayElem; basicData.filter.categoryBits = static_cast
(fixtureData->objectForKey("filter_categoryBits"))->intValue(); basicData.filter.maskBits = static_cast
(fixtureData->objectForKey("filter_maskBits"))->intValue(); basicData.filter.groupIndex = static_cast
(fixtureData->objectForKey("filter_groupIndex"))->intValue(); basicData.friction = static_cast
(fixtureData->objectForKey("friction"))->floatValue(); basicData.density = static_cast
(fixtureData->objectForKey("density"))->floatValue(); basicData.restitution = static_cast
(fixtureData->objectForKey("restitution"))->floatValue(); basicData.isSensor = (bool)static_cast
(fixtureData->objectForKey("isSensor"))->intValue(); CCString *cb = static_cast
(fixtureData->objectForKey("userdataCbValue")); int callbackData = 0; if (cb) callbackData = cb->intValue(); std::string fixtureType = static_cast
(fixtureData->objectForKey("fixture_type"))->m_sString; if (fixtureType == "POLYGON") { CCArray *polygonsArray = (CCArray *)(fixtureData->objectForKey("polygons")); CCObject *dicArrayElem; CCARRAY_FOREACH(polygonsArray, dicArrayElem) { FixtureDef *fix = new FixtureDef(); fix->fixture = basicData; // copy basic data fix->callbackData = callbackData; b2PolygonShape *polyshape = new b2PolygonShape(); int vindex = 0; CCArray *polygonArray = (CCArray*)dicArrayElem; assert(polygonArray->count() <= b2_maxPolygonVertices); CCObject *piter; CCARRAY_FOREACH(polygonArray, piter) { CCString *verStr = (CCString*)piter; CCPoint offset = CCPointFromString(verStr->getCString()); vertices[vindex].x = (offset.x / ptmRatio) ; vertices[vindex].y = (offset.y / ptmRatio) ; vindex++; } polyshape->Set(vertices, vindex); fix->fixture.shape = polyshape; // create a list *nextFixtureDef = fix; nextFixtureDef = &(fix->next); } } else if (fixtureType == "CIRCLE") { FixtureDef *fix = new FixtureDef(); fix->fixture = basicData; // copy basic data fix->callbackData = callbackData; CCDictionary *circleData = (CCDictionary *)fixtureData->objectForKey("circle"); b2CircleShape *circleShape = new b2CircleShape(); circleShape->m_radius = static_cast
(circleData->objectForKey("radius"))->floatValue() / ptmRatio; CCPoint p = CCPointFromString(static_cast
(circleData->objectForKey("position"))->getCString()); circleShape->m_p = b2Vec2(p.x / ptmRatio, p.y / ptmRatio); fix->fixture.shape = circleShape; // create a list *nextFixtureDef = fix; nextFixtureDef = &(fix->next); } else { CCAssert(0, "Unknown fixtureType"); } } // add the body element to the hash shapeObjects[bodyName] = bodyDef; } }
3.首先#include "GB2ShapeCache-x.h",使用GB2ShapeCache的addShapesWithFile方法加载plist文件
4.定义资源名称数组,需要与编辑器中定义的资源名称相同。
5.通过GB2ShapeCache的addFixturesToBody方法建立夹具定义与刚体的关联。
效果图
工程地址:https://coding.net/u/linchaolong/p/PhysicsEditorDemo/git
相关文章: