Cocos2d使用Box2d做碰撞处理
来源:互联网 发布:ie8 js serialize 编辑:程序博客网 时间:2024/06/16 01:31
在Cocos2d下已经留下了Box2d的接口,使用Box2d来做碰撞检测有效方便。
Box2d在与Cocos2d的世界进行对接的时候,要保证BOX2d的世界世界被同步的更新。如果设置了物理参数比如碰撞,重力,速度,加速度,那么将会产生非常逼真的效果。用来制作带有物理效果的也是十分方便的。
要使用Box2D的碰撞检测,大致要做下面几件事:
一、创建精灵的body,为body添加夹具,这个夹具就是在b2世界中用来物体的外形,根据此外性来进行碰撞检测。
二、周期性更新body的位置(按照每帧或每两帧等)。
三、打开碰撞监听,重写监听的处理函数,获取碰撞点信息保存到list。
四、周期性处理碰撞信息list,维护list。
接下来就分别介绍上述几步骤。
一、创建Body,添加夹具
先上代码:
b2Body* GameLayer::AddBoxBodyForSprite(cl* pcl,int type){if(this->m_world->IsLocked()){return NULL;} b2BodyDef bd; //创建body,设置位置 bd.type = b2_dynamicBody; bd.position = b2Vec2((float)(pFish->getSpriteFish()->getPosition().x / PT_RATIO),(float)(pFish->getSpriteFish()->getPosition().y /PT_RATIO)); bd.userData = pcl; //userdata用来存放用户数据 b2Body* spriteBody = m_world->CreateBody(&bd); CCString* FixName = CCString::createWithFormat("fish%02d_bodyft",type); GB2ShapeCache *sc = GB2ShapeCache::sharedGB2ShapeCache(); //解析精灵外形多边形 sc->addFixturesToBody(spriteBody, FixName->getCString()); //按照多边形轮廓为精灵添加物理实体 return spriteBody;}从上面的代码主要完成的就是添加body,然后创建body的夹具。在添加body时候注意在userdata上添加需要保存的内容,可以为变量或者指针,此例作为碰撞检测,应该保存碰撞实例的指针便于后面进行碰撞处理。
创建夹具使用PhysicsEditor工具,它可以手动选取精灵的轮廓编辑成plist文件,然后再程序中解析用于为该精灵创建合适的夹具。在选取轮廓是应该适中的选取点数,保证基本外形特征,同时尽量减少多边形的顶点,正阳Box2d在迭代计算式计算量小。
二、更新Box2d中物体的坐标
先贴上上代码。
if(this->m_world->IsLocked()){return ;}if (m_world) m_world->Step(dt, 10, 10); // 基于cocos2d的精灵位置来更新box2d的body位置 for(b2Body* b = m_world->GetBodyList(); b; b = b->GetNext()) { if(b&&b->GetUserData() != NULL) { for (b2Fixture* Fixture = b->GetFixtureList(); Fixture; Fixture = Fixture->GetNext()) { b2Filter data = Fixture->GetFilterData(); group = data.groupIndex; break; } if(group==-2) { Bullet* pBullet = (Bullet*)b->GetUserData(); if (pBullet&&pBullet->getSpriteBullet()) { b2Vec2 pt = b2Vec2((float)(pBullet->getSpriteBullet()->getPosition().x / PT_RATIO), (float)(pBullet->getSpriteBullet()->getPosition().y / PT_RATIO)); float angle = CC_DEGREES_TO_RADIANS(pBullet->getSpriteBullet()->getRotation()); b->SetTransform(pt, -angle);//与cocos中转向相反 } } } }首先,在更新坐标box2d世界坐标以前,先将PTM_RATIO这个数一般定义为: 32.0,在box 世界中 是以 米 为单位的,这里是将坐标兑换为box世界中的米。这就相当一个比例尺,在box2d的世界里面,最佳的尺寸就是10m以内,进行一个缩放转换。
当然首先要创建一b2world:
void GameLayer::InitB2World(){b2Vec2 gravity(0.0f, -0.0f);bool doSleep = false;m_world = new b2World(gravity);m_world->SetAllowSleeping(doSleep);m_world->SetContinuousPhysics(true);contactListener = new MyContactListener();}在创建被world的时候可以设置是否存在重力,是否可以休眠,设置监听。
在更新时通过m_word的实例来遍历其中的每一个body,通过body的userdata查询精灵并利用精灵来更新物体在世界中的位置。注意在更新以前一定的保证上一次迭代完成,通过判断是否世界上锁来得到当前状态。
三、碰撞监听
打开碰撞监听最好重写一个继承自b2ContactListener类的类,然后覆盖碰撞响应函数 ,在响应函数得到碰撞点信息。代码MyContact.h:
class MyContact{public: b2Fixture* fixtureA; b2Fixture* fixtureB; b2Vec2 contactPoint;bool operator==(const MyContact& other) const { return (fixtureA == other.fixtureA) && (fixtureB == other.fixtureB); }};class MyContactListener : public b2ContactListener {public:MyContactListener();~MyContactListener();std::list<MyContact> contact_list;//std::vector<MyContact>_contacts; virtual void BeginContact(b2Contact *contact);//virtual void EndContact(b2Contact *contact);virtual void PreSolve(b2Contact *contact, const b2Manifold *oldManifold);virtual void PostSolve(b2Contact *contact, const b2ContactImpulse *impulse);};在MyContact类中也定义了一个contact_list用来保存碰撞点的信息,定义MyContact结构体来格式化存储碰撞点。下面是MyContact.cpp代码:
#include "MyContact.h"MyContactListener::MyContactListener(){}MyContactListener::~MyContactListener() {}void MyContactListener::BeginContact(b2Contact *contact) { if (contact) { MyContact mc; mc.fixtureA = contact->GetFixtureA(); mc.fixtureB = contact->GetFixtureB(); for( std::list<MyContact>::iterator it = contact_list.begin();//重要,本例一次只能采样一个碰撞点 it != this->contact_list.end(); ++it) { MyContact& contact = *it; if((contact.fixtureA->GetUserData() == mc.fixtureA->GetUserData())&& (contact.fixtureB->GetUserData() == contact.fixtureB->GetUserData())) { return ; } else if((contact.fixtureA->GetUserData() == mc.fixtureB->GetUserData())&& (contact.fixtureB->GetUserData() == contact.fixtureA->GetUserData())) { return ; } } //定义一个b2WorldManifold对象,用来获取并存储碰撞点的全局坐标 b2WorldManifold* manifold = new b2WorldManifold(); //通过GetWorldManifolde方法,计算出碰撞点的全局坐标,并存储到manifold变量中 contact->GetWorldManifold(manifold); //获取碰撞点 mc.contactPoint = manifold->points[0]; contact_list.push_back(mc); } // B2_NOT_USED(contact); } //当刚体发生碰撞开始的时候调用void MyContactListener::EndContact(b2Contact *contact) {}//当刚体结束碰撞时调用void MyContactListener::PreSolve(b2Contact *contact, const b2Manifold *oldManifold){B2_NOT_USED(contact); B2_NOT_USED(oldManifold);} //碰撞开始前调用void MyContactListener::PostSolve(b2Contact *contact, const b2ContactImpulse *impulse) {B2_NOT_USED(contact); B2_NOT_USED(impulse);}一共有四个碰撞处理函数,分别是碰撞开始时候,碰撞过程中,碰撞预处理。需要重写那个函数根须实际需要决定。但需要注意同一时间可能两个物体有多个碰撞点存在,注意排除重复点。
四、碰撞处理函数
如果碰撞点很多处理起来就很吃力,需要想办法分支节约效率,同时要保证处理的实时性,不能对一个碰撞
for( std::list<MyContact>::iterator it = contactListener->contact_list.begin(); it != contactListener->contact_list.end(); ++it) { ..... } contactListener->contact_list.clear();//清空待待处理的contactlist,防止重复出错便利碰撞list记录,根据userdata处理。同时在最后记得清空整个list。
以上几个步骤基本上就已经开阔了碰撞处理的基本方法,调试时可以打开调试绘图查看碰撞区域,以及触发时间。
打开碰撞调试区域显示:
debugDraw = new GLESDebugDraw(PT_RATIO); //这里新建一个 debug渲染模块 m_world->SetDebugDraw(debugDraw); //设置 uint32 flags = 0; flags += b2Draw::e_shapeBit ; //b2Draw::e_centerOfMassBit; //获取需要显示debugdraw的块 //b2Draw::e_aabbBit; //AABB块 //b2Draw::e_centerOfMassBit; 物体质心 //b2Draw::e_jointBit; //关节 //b2Draw::e_shapeBit; 形状 debugDraw->SetFlags(flags); //需要显示那些东西 draw(); //画出来最后通过调用draw函数进行会图,draw中那些如下代码:
CCNode::draw();ccGLEnableVertexAttribs(kCCVertexAttribFlag_Position);kmGLPushMatrix(); m_world->DrawDebugData(); //这个一定要写 kmGLPopMatrix();通过上面的实质将会吧碰撞多边形显示出来,特变注意,显示调试区域的时候,一定要将场景图的背景去掉,直接以黑双色为背景,否则调试区域可能显示不出来。
- Cocos2d使用Box2d做碰撞处理
- cocos2d-x 使用box2d来做碰撞检测(且仅用来做碰撞检测)
- 使用Box2d做碰撞检测
- cocos2d box2d b2ContactListener 碰撞监听、碰撞处理、碰撞筛选
- <cocos2d-x for wp7>使用box2d来做碰撞检测(且仅用来做碰撞检测)
- 16. 如何使用box2d来做碰撞检测(且仅用来做碰撞检测)
- (译)如何使用box2d来做碰撞检测(且仅用来做碰撞检测)
- 如何使用box2d来做碰撞检测(且仅用来做碰撞检测)
- (译)如何使用box2d来做碰撞检测(且仅用来做碰撞检测)
- 使用box2d来做碰撞检测(且仅用来做碰撞检测)
- cocos2d中使用chipmunk做碰撞检测
- [cocos2d-x]Box2D 碰撞过滤规则
- cocos2d中使用box2d
- Box2D的Edge Shape的碰撞处理
- Cocosd2d 使用box2d完成碰撞检测
- cocos2d box2d 基础 知识 创建人物、金币、碰撞 检测
- cocos2d-x+box2d+tiled 制作无规则碰撞地图
- 实例介绍Cocos2d-x中Box2D物理引擎:碰撞检测
- 迷你播放器--综述
- 病狗问题以及帽子颜色那个题
- 爱到深处无言
- hdu 1060 2014731
- C语言入门——C语言学习日志5
- Cocos2d使用Box2d做碰撞处理
- 【鸟哥Linux学习笔记】关于Linux磁盘管理和文件系统(2)
- 代码重构之一 变质的代码
- java中final关键字的使用
- 烦死
- Json整理
- csdn开源夏令营中期总结
- Codeforces Round #259 (Div. 2)-B. Little Pony and Sort by Shift
- iOS下用一行代码实现tableview(collectionview)的parallax效果