玩轉cocos2d-x(二)支持PhysicsEditor

PhysicsEditor 是一個針對2D物理引擎的碰撞外形描點工具。(關於這個描述,聽起來比較拗口,具體的可以參考官網

這個工具是收費的,可支持windows,mac osx。同類的工具免費的有VertexHelper。

可從github上clone,通過xcode  build後將product目錄下的app文件拖到Application目錄安裝使用。

github地址:https://github.com/jfahrenkrug/VertexHelper.git

相比較來說PhysicsEditor有幾個優點:

1、支持windows平臺

2、可到處plist文件,在構建shape的時候減少人肉複製頂點座標的時間,提升效率;同時保證代碼的整潔。

3、官網提供了對cocos2d-x的支持 PyhsicsEditor對cocos2d-x的官方支持

但悲催的是官網的支持使用的是cocos2d-x 1.x版本的,而現在cocos2d-x已更新到2.x了,已有很多接口變動了。

具體可以看cocos2d-x 官網wiki http://www.cocos2d-x.org/projects/cocos2d-x/wiki/Cocos2d-x_v20_migration_guide

針對cocos2d-x 2.x版本的接口改動,對PhysicsEditor的官方支持做了一些修改:

1、將類名前綴修改爲CC

2、將1.x版本的CCDictionary,CCMutableArray 的接口調整爲 2.x的CCDictionary,CCArray的接口

3、更新CCFileUtils的接口使用

4、調整原來的添加bodyDef到 map中的代碼位置調整(減少不必要的循環操作)

下面貼出源碼:

//
//  CCShapeCache.h
//

#ifndef __CCSHAPECACHE_H__
#define __CCSHAPECACHE_H__


#include "cocos2d.h"
USING_NS_CC;

class BodyDef;
class b2Body;

namespace cocos2d {
	class CCShapeCache : public CCObject{
	public:
		// Static interface
		static CCShapeCache* sharedShapeCache(void);
		
	public:
		
        bool init();
		
        void addShapesWithFile(const std::string &plist);
		
        void addFixturesToBody(b2Body *body, const std::string &shape);
		
        cocos2d::CCPoint anchorPointForShape(const std::string &shape);
		
        void reset();
        
		float getPtmRatio() { return ptmRatio; }
        
		~CCShapeCache() {}
		
	private:
		std::map<std::string, BodyDef *> shapeObjects;
		
        CCShapeCache(void) {}
		
        float ptmRatio;
	};
}


#endif /* defined(__CCSHAPECACHE_H__) */

//
//  CCShapeCache.cpp
//
//

#include "CCShapeCache.h"
#include "Box2D.h"
#include "CCNS.h"

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 CCShapeCache *_sharedShapeCache = NULL;

CCShapeCache* CCShapeCache::sharedShapeCache(void) {
	if (!_sharedShapeCache) {
		_sharedShapeCache = new CCShapeCache();
        _sharedShapeCache->init();
	}
	
	return _sharedShapeCache;
}

bool CCShapeCache::init() {
	return true;
}


void CCShapeCache::reset() {
	std::map<std::string, BodyDef *>::iterator iter;
	for (iter = shapeObjects.begin() ; iter != shapeObjects.end() ; ++iter) {
		delete iter->second;
	}
	shapeObjects.clear();
}

void CCShapeCache::addFixturesToBody(b2Body *body, const std::string &shape) {
	std::map<std::string, BodyDef *>::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 CCShapeCache::anchorPointForShape(const std::string &shape) {
	std::map<std::string, BodyDef *>::iterator pos = shapeObjects.find(shape);
	assert(pos != shapeObjects.end());
	
	BodyDef *bd = (*pos).second;
	return bd->anchorPoint;
}


void CCShapeCache::addShapesWithFile(const std::string &plist)
{
    const char* fullName = CCFileUtils::sharedFileUtils()->fullPathFromRelativePath(plist.c_str());
    CCDictionary* dict = CCDictionary::createWithContentsOfFile(fullName);
    
    CCAssert(dict != NULL, "Shape-file not found"); // not triggered - cocos2dx delivers empty dict if non was found
    CCAssert(dict->count() != 0, "plist file empty or not existing");
    
    CCDictionary* metadataDict = (CCDictionary*)dict->objectForKey("metadata");
    int format = metadataDict->valueForKey("format")->intValue();
    ptmRatio = metadataDict->valueForKey("ptm_ratio")->floatValue();
    CCAssert(format == 1, "Format not supported");
    
    CCDictionary* bodyDict = (CCDictionary*)dict->objectForKey("bodies");
    b2Vec2 vertices[b2_maxPolygonVertices];
    CCLog("bodydict count %d ",bodyDict->count());
    
    CCDictElement* pElement = NULL;
    CCDICT_FOREACH(bodyDict, pElement)
    {
        CCDictionary* bodyData = (CCDictionary*)pElement->getObject();
        CCLog("body key %s -> bodyData count %d",pElement->getStrKey(),bodyData->count());
        BodyDef* bodyDef = new BodyDef();
        shapeObjects[pElement->getStrKey()] = bodyDef;
        
        CCLog("anchorpoint %s",bodyData->valueForKey("anchorpoint")->getCString());
        bodyDef->anchorPoint = CCPointFromString(bodyData->valueForKey("anchorpoint")->getCString());
        
        CCArray* fixtureList = (CCArray*)(bodyData->objectForKey("fixtures"));
        FixtureDef **nextFixtureDef = &(bodyDef->fixtures);
        
        CCObject* pObj = NULL;
        CCARRAY_FOREACH(fixtureList, pObj)
        {
            b2FixtureDef basicData;
            CCDictionary* fixtureData = (CCDictionary*)pObj;
            
            basicData.filter.categoryBits = fixtureData->valueForKey("filter_categoryBits")->intValue();
            basicData.filter.maskBits = fixtureData->valueForKey("filter_maskBits")->intValue();
            basicData.filter.groupIndex = fixtureData->valueForKey("filter_groupIndex")->intValue();
            basicData.friction = fixtureData->valueForKey("friction")->floatValue();
            basicData.density = fixtureData->valueForKey("density")->floatValue();
            basicData.restitution = fixtureData->valueForKey("restitution")->floatValue();
            basicData.isSensor = fixtureData->valueForKey("isSensor")->boolValue();
            
            int cb = fixtureData->valueForKey("userdataCbValue")->intValue();
            
            int callbackData = cb ? cb : 0;
            std::string fixtureType = fixtureData->valueForKey("fixture_type")->m_sString;
            if(fixtureType == "POLYGON")
            {
                CCArray* polygonsArray = (CCArray*)fixtureData->objectForKey("polygons");
                CCObject* pObject;
                CCARRAY_FOREACH(polygonsArray, pObject)
                {
                    FixtureDef *fix = new FixtureDef();
                    fix->fixture = basicData; // copy basic data
                    fix->callbackData = callbackData;
                    
                    b2PolygonShape *polyshape = new b2PolygonShape();
                    int vindex = 0;
                    
                    CCArray* polygonArray = (CCArray*)pObject;
                    assert(polygonsArray->count() <= b2_maxPolygonVertices);
                    
                    CCObject* pPointObject;
                    CCARRAY_FOREACH(polygonArray, pPointObject)
                    {
                        CCString* pointStr = (CCString*)pPointObject;
                        CCPoint offset = CCPointFromString(pointStr->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 = circleData->valueForKey("radius")->floatValue() / ptmRatio;
				CCPoint p = CCPointFromString(circleData->valueForKey("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");
            }
        }
    }
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章