【Cocos2d-x】PhysicsEditor的使用

本文介绍了如何使用PhysicsEditor在Cocos2d-x中创建物理碰撞形状。首先,讲述了PhysicsEditor的下载与安装,然后详细讲解了编辑器的使用步骤,包括添加图片、编辑顶点、设置导出格式和参数。接着,阐述了在Cocos2d-x2.2.1中导入和使用导出的.plist文件的方法,包括替换废弃API、加载文件和关联夹具定义。最后提供了源码下载链接。
摘要由CSDN通过智能技术生成

下载与安装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

点击下载源码


相关文章:

【Cocos2d-x】物理引擎使用入门

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值