Cocos2d-x_Box2D刚体使用PhysicsEditor工具生成形状_小可_子衿的博客-程序员宅基地

技术标签: Cocos2d-x  刚体  PhysicsEditor  Cocos2d-x开发  Box2D  形状  

众所周知,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_BEGIN
class 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 30

HelloWorld::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, 0, b2Vec2(0, -winSize.height / 2 / PTM_RATIO), 0);

	b2FixtureDef fixtureDef;
	fixtureDef.shape = &groundBox;
	fixtureDef.density = 1;  //密度
	fixtureDef.friction = 0.5f;  //摩擦因数
	fixtureDef.restitution = 0.4f;  //弹性因数

	// 底部
	groundBody->CreateFixture(&fixtureDef);

	// 顶部
	groundBox.SetAsBox(winSize.width / 2 / PTM_RATIO, 0, b2Vec2(0, 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);
	groundBody->CreateFixture(&groundBox, 0);

	// 右边
	groundBox.SetAsBox(0, winSize.height / 2 / PTM_RATIO, b2Vec2(winSize.width / 2 / PTM_RATIO, 0), 0);
	groundBody->CreateFixture(&groundBox, 0);

	// 设置精灵
	CCLabelTTF *label = CCLabelTTF::create("屏幕顶端", "Arial", 32);
	this->addChild(label, 0);
	label->setColor(ccc3(0, 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;
}


版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/c201038795050/article/details/44886963

智能推荐

BZOJ 4475: [Jsoi2015]子集选取 快速幂_BlackJack_的博客-程序员宅基地

4475: [Jsoi2015]子集选取Time Limit: 1 Sec Memory Limit: 512 MBSubmit: 217 Solved: 159[Submit][Status][Discuss]DescriptionInput输入包含一行两个整数N和K,1Output一行一个整数,表示不同方案数目模1,000,000,0

flutter SliverAppBar 随内容一起滑动的头部 - 滞留头部_sliverappbar flexiblespacebar跟随滑上去_马志武的博客-程序员宅基地

一个与CustomScrollView集成的应用程序栏。Sliver应用程序栏通常用作CustomScrollView的第一个子项,它允许应用程序栏与滚动视图集成,以便它可以根据滚动偏移量在高度上变化,或者在滚动视图中的其他内容上方浮动。参数详解属性 说明 leading 头部组件(无法使用网络图片) automaticallyImplyLeadi..._sliverappbar flexiblespacebar跟随滑上去

数据结构实验7《基于Dijsktra算法的最短路径求解》_基因沉默小RNA的博客-程序员宅基地

(visual studio 2019可运行)输入及输出要求见《数据结构C语言(第二版)》严蔚敏版【本文仅用于啥都看不懂还想交作业选手】加了一点输入异常的反馈基于基于Dijsktra算法的最短路径求解 - 简书改动(这是一个我终于明白并不需要一次性统一输出的故事)#include<iostream>using namespace std;#define MAXSIZE 100#define OK 1typedef int Status;//用两个数组分别存储顶点表

cuda版本和NVIDIA兼容性问题_ChaoFeiLi的博客-程序员宅基地

安装了cuda 10.2,结果告诉我不兼容,所以重新安装一下cuda 10.0http://chaofei.baiduux.com/h5/zh-lcf.html

关于Microwindows(nano x)2410的移植_mxdly的博客-程序员宅基地

需要安装arm-linux-gcc2.95.3,好像其他的也可以吧~没试过。安装方法网上一搜到处都是,不在此做介绍了。1.需要在microwindows官网上下载一个工具包,ftp://microwindows.censoft.com/pub/microwindows/microwindows-0.90.tar.gz [root@ root]# tar zxf microwindo

随便推点

vue-elementui switch开关的使用_vue amazing ui switch_zoe_xx的博客-程序员宅基地

vue-elementui switch开关的使用话不多说上代码相关标签释义:active-color:活跃时的颜色inactive-color:不活跃时的颜色active-value:活跃时的值inactive-value:不活跃时的值@change修改显示状态事件table中显示状态代码片段<el-table-column prop="showStatus" header-align="center" align="center" label="显示状态"> _vue amazing ui switch

opencv+Kinect2.0调用Visual Gesture Builder制作的动作_cccccc1212的博客-程序员宅基地

先把制作好的gba文件复制到程序的目录中去。 因为动作分为静态动作和连续动作,所以对于这个两种动作的代码也会有一些不一样。 先是静态的:#include "opencv2/core.hpp"#include "opencv2/imgproc.hpp"#include "opencv2/highgui.hpp"#include "opencv2/videoio.hpp"#include <

位操作基础篇之位运算符全面总结_Dev-L的博客-程序员宅基地

在计算机中所有数据都是以二进制的形式储存的。位运算其实就是直接对在内存中的二进制数据进行操作,因此处理数据的速度非常快。在实际编程中,如果能巧妙运用位操作,完全可以达到四两拨千斤的效果,正因为位操作的这些优点,所以位操作在各大IT公司的笔试面试中一直是个热点问题。因此本文将对位操作进行如下方面总结: 位操作基础,用一张表描述位操作符的应用规则并详细解释。 常用位

样条函数(spline function)—— 分段多项式函数(piecewise polynomial function)_五道口纳什的博客-程序员宅基地

1. 分段多项式函数 样条函数是某种意义上的分段函数。Spline (mathematics) - Wikipedia最简单的样条函数是一种分段多项式函数(piecewise polynomial function),样条函数 S:[a,b]→RS:[a, b]\rightarrow \mathbb R。SS 是在定义域 [a,b][a, b] 上分段定义的,我们将 [a,b][a, b] 划_样条函数

wireshark抓包比较http与https头信息_数据包http头在哪看_dengjili的博客-程序员宅基地

软件准备,wireshark1.打开,观察一会儿,看看哪些端口网络有活跃2.我现在要测外网网络,我这里是WLAN接口双击WANL直接开始准备一个http协议的网站这里准备:www.runoob.com输入过滤网站,记得回车http.host == www.runoob.com刷新网址查看http中的 request 与 response,执行下面操作可以看出是明文..._数据包http头在哪看

IT领域好的网站总结(待续........)_weixin_34360651的博客-程序员宅基地

IT:http://www.csdn.net(.net/程序员社区)http://www.51cto.com/(服务于各个中小型企业的技术大拿)http://www.51aspx.com(asp.net/源码)http://www.ccidnet.com/(比较杂。本人上的比较少。)http://www.cnblogs.com/(这个不用说了。)http://www.zdnet...

推荐文章

热门文章

相关标签