Cocos2d-x_Box2D刚体使用PhysicsEditor工具生成形状

Cocos2d-x_Box2D刚体使用PhysicsEditor工具生成形状,第1张

概述众所周知,Box2D中的刚体形状如果比较简单,我们可以使用Box2D中的几个形状子类生成,但是如果我们游戏中的刚体的形状比较复杂,那我们需要使用第三方工具生成,而现在Box2D的第三方工具很少,目前所知道的只有两个:一个是在Mac系统下使用的  VertexHelper工具,另一个是Windows系统下使用的PhysicsEditor工具,我们这里就来讲讲PhysicsEditor工具导出的p 众所周知,Box2D中的刚体形状如果比较简单,我们可以使用Box2D中的几个形状子类生成,但是如果我们游戏中的刚体的形状比较复杂,那我们需要使用第三方工具生成,而现在Box2D的第三方工具很少,目前所知道的只有两个:一个是在Mac系统下使用的 

VertexHelper工具,另一个是windows系统下使用的PhysicsEditor工具,我们这里就来讲讲PhysicsEditor工具导出的pList文件在Cococs2d-x中的使用方法。

注意:目前最新版本的PhysicsEditor工具的安装目录下面的Demo里面的GB2ShapeCache-x解析类已经不支持Cocos2d-x 2.x版本,但是我们可以在它原来的基础上进行修改,修改后的GB2ShapeCache-x解析类经过测试,对Cocos2d-x 2.x已经全部支持。下面给出修改后的GB2ShapeCache-x解析类文件:

#ifndef GB2ShapeCache_x_h#define GB2ShapeCache_x_h #include "cocos2d.h"#include <map>class BodyDef;class b2Body;NS_CC_BEGINclass GB2ShapeCache {public:    static GB2ShapeCache* sharedGB2ShapeCache(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; }    ~GB2ShapeCache() {} private:	std::map<std::string,BodyDef *> shapeObjects;    GB2ShapeCache(voID) {}    float ptmRatio;};NS_CC_END#endif


#include "GB2ShapeCache-x.h"#include "Box2D/Box2D.h"#include "cocoa/CCNS.h"using namespace cocos2d;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<std::string,BodyDef *>::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<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 GB2ShapeCache::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;}typedef CCDictionary ObjectDict;voID GB2ShapeCache::addShapesWithfile(const std::string &pList){	string fullname = CCfileUtils::sharedfileUtils()->fullPathForfilename(pList.c_str());	CCDictionary* dict = CCDictionary::createWithContentsOffile(fullname.c_str());	cclOG(fullname.c_str());	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;					CCObject* pObject;					CCAssert(polygonsArray->count(),"polygonsArray = 0!");					CCARRAY_FOREACH(polygonArray,pObject)					{						CCPoint offset = CCPointFromString(((CCString *)pObject)->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");			}		}	}}

针对PhysicsEditor工具的使用,很简单,可以自己查找资料,这里就不再累述,我们把导出来的pList文件拷贝到Resource目录下就可以了,下面给出使用代码:

#ifndef __HELLO_WORLD_H__#define __HELLO_WORLD_H__#include "cocos2d.h"#include "cocos-ext.h"#include "Box2D/Box2D.h"USING_NS_CC;USING_NS_CC_EXT;class HelloWorld : public cocos2d::cclayer {public:	HelloWorld();    virtual ~HelloWorld();        static cocos2d::CCScene* scene();    	virtual voID onEnter();	virtual voID onExit();	virtual bool cctouchBegan(CCtouch *ptouch,CCEvent *pEvent);	virtual voID cctouchended(CCtouch *ptouch,CCEvent *pEvent);	virtual bool init();    virtual voID update(float dt);    	CREATE_FUNC(HelloWorld);private:    b2World* world;private:	voID addNewSpriteWithCoords(cocos2d::CCPoint p);};#endif

////  HelloWorldScene.cpp//  Demo////  Created by Andreas L枚w on 11.01.12.//  copyright codeanDWeb.de 2012. All rights reserved.//#include "HelloWorldScene.h"#include "SimpleAudioEngine.h"#include "GB2ShapeCache-x.h"#define PTM_RATIO 30HelloWorld::HelloWorld(){}HelloWorld::~HelloWorld(){	if (world)	{		delete world;		world = NulL;	}}bool HelloWorld::init(){	if (!cclayer::init())	{		return false;	}	// 载入物理形状	GB2ShapeCache::sharedGB2ShapeCache()->addShapesWithfile("Box2D.pList");	// 开启多点触控	//this->settouchEnabled(true);	// 开启重力加速	//this->setAccelerometerEnabled(true);	CCSize winSize = CCDirector::sharedDirector()->getWinSize();	// 定义重力方向	b2Vec2 gravity;	gravity.Set(0.0f,-10.0f);	// 刚体是否睡眠	bool doSleep = true;	bool continuous = true;	world = new b2World(gravity);	world->SetAllowSleePing(doSleep);	world->SetContinuousPhysics(continuous);	b2BodyDef groundBodyDef;	groundBodyDef.position.Set(winSize.wIDth / 2 / PTM_RATIO,winSize.height / 2 / PTM_RATIO);	b2Body* groundBody = world->CreateBody(&groundBodyDef);	// 定义一个地面盒形状	b2polygonShape groundBox;	groundBox.SetAsBox(winSize.wIDth / 2 / PTM_RATIO,b2Vec2(0,-winSize.height / 2 / PTM_RATIO),0);	b2FixtureDef fixtureDef;	fixtureDef.shape = &groundBox;	fixtureDef.density = 1;  //密度	fixtureDef.friction = 0.5f;  //摩擦因数	fixtureDef.restitution = 0.4f;  //d性因数	// 底部	groundBody->CreateFixture(&fixtureDef);	// 顶部	groundBox.SetAsBox(winSize.wIDth / 2 / PTM_RATIO,winSize.height / 2 / PTM_RATIO),0);	groundBody->CreateFixture(&groundBox,0);	// 左边	groundBox.SetAsBox(0,winSize.height / 2 / PTM_RATIO,b2Vec2(-winSize.wIDth / 2 / PTM_RATIO,0),0);	// 右边	groundBox.SetAsBox(0,b2Vec2(winSize.wIDth / 2 / PTM_RATIO,0);	// 设置精灵	cclabelTTF *label = cclabelTTF::create("屏幕顶端","Arial",32);	this->addChild(label,0);	label->setcolor(ccc3(0,255));	label->setposition(CCPointMake(winSize.wIDth / 2,winSize.height - 50));	this->addNewSpriteWithCoords(CCPointMake(winSize.wIDth / 2,winSize.height / 2));	this->scheduleUpdate();	return true;}string names[] = {	"BoxA"	/*"hotdog","drink","icecream","icecream2","icecream3","hamburger","orange"*/};voID HelloWorld::addNewSpriteWithCoords(CCPoint p){	string name = names[0];//names[rand() % 7];	cclOG("name:%s",name.c_str());	CCSprite *sprite = CCSprite::create((name + ".png").c_str());	sprite->setposition(p);	this->addChild(sprite);	b2BodyDef bodyDef;	bodyDef.type = b2_dynamicBody;	bodyDef.position.Set(p.x / PTM_RATIO,p.y / PTM_RATIO);	bodyDef.userData = sprite;	b2Body *body = world->CreateBody(&bodyDef);	// 刚体添加夹具	GB2ShapeCache::sharedGB2ShapeCache()->addFixturesToBody(body,name.c_str());	sprite->setAnchorPoint(GB2ShapeCache::sharedGB2ShapeCache()->anchorPointForShape(name.c_str()));}voID HelloWorld::update(float dt){	int veLocityIterations = 8;	int positionIterations = 3;	world->Step(dt,veLocityIterations,positionIterations);	for (b2Body* b = world->GetbodyList(); b; b = b->GetNext())	{		if (b->GetUserData() != NulL)		{			CCSprite* myActor = (CCSprite*)b->GetUserData();			myActor->setposition(CCPointMake(b->Getposition().x * PTM_RATIO,b->Getposition().y * PTM_RATIO));			myActor->setRotation(-1 * CC_radians_TO_degrees(b->GetAngle()));		}	}}voID HelloWorld::onEnter(){	CCDirector::sharedDirector()->gettouchdispatcher()->addTargetedDelegate(this,-128,true);	cclayer::onEnter();}voID HelloWorld::onExit(){	CCDirector::sharedDirector()->gettouchdispatcher()->removeDelegate(this);	cclayer::onExit();}bool HelloWorld::cctouchBegan(CCtouch *ptouch,CCEvent *pEvent){	return true;}voID HelloWorld::cctouchended(CCtouch *ptouch,CCEvent *pEvent){	CCPoint pt = ptouch->getLocation();	this->addNewSpriteWithCoords(pt);}//voID HelloWorld::cctouchesBegan(CCSet *ptouches,CCEvent *pEvent)//{//	cclOG("HelloWorld::cctouchesBegan");//	CCSetIterator it;//	CCtouch *touch;////	for (it = ptouches->begin(); it != ptouches->end(); it++)//	{//		touch = (CCtouch*)(*it);////		if (!touch)//			break;////		CCPoint location = touch->getLocation();//		this->addNewSpriteWithCoords(location);//	}//}CCScene* HelloWorld::scene(){	CCScene *scene = CCScene::create();	HelloWorld *layer = HelloWorld::create();	scene->addChild(layer);	return scene;}
总结

以上是内存溢出为你收集整理的Cocos2d-x_Box2D刚体使用PhysicsEditor工具生成形状全部内容,希望文章能够帮你解决Cocos2d-x_Box2D刚体使用PhysicsEditor工具生成形状所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://www.outofmemory.cn/web/1053422.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-25
下一篇 2022-05-25

发表评论

登录后才能评论

评论列表(0条)

保存