cocos2dx读书笔记(Box2D 物理引擎)

转载:http://blog.youkuaiyun.com/qq_17749439/article/details/38046633

转载:http://blog.youkuaiyun.com/u012945598/article/details/17787243

Box2dHandler.h

[cpp]  view plain copy
  1. #include "cocos2d.h"  
  2. #include "Box2D.h"  
  3. #include "GLES-Render.h"  
  4. USING_NS_CC;  
  5. #define PTM_RATIO 32  
  6.   
  7. class B2Sprite :public CCSprite  
  8. {  
  9. public:  
  10.  //   static B2Sprite *spriteWithSpriteFrameName(const char*file);  
  11.  //   bool initWithSpriteFrameName(const char *pszSpriteFrameName);  
  12. //    物理世界的“物体”  
  13.     CC_SYNTHESIZE(b2Body*, m_b2Body, B2Body);  
  14. //    是否死去  
  15. //    IsDead为true,表示彻底从屏幕上消失  
  16.     CC_SYNTHESIZE(bool, m_isDead, IsDead);  
  17. //    是否存活  
  18. //    IsAlive为true,则物体存活,代表仍然存在碰撞体积,需要考虑碰撞  
  19.     CC_SYNTHESIZE(bool, m_isAlive, IsAlive);  
  20. };  
  21.   
  22. class Box2dHandler:public CCNode,public b2ContactListener  
  23. {  
  24.     public:  
  25. //    用于调试绘图  
  26.     GLESDebugDraw *m_debugDraw;  
  27. //    物理世界  
  28.     b2World *m_world;  
  29. //    用于保存死亡对象对容器  
  30. //    typedef pair<b2Fixture *, b2Fixture *> MyContact;  
  31. //    set<MyContact> m_contacts;  
  32. //    初始化物理世界  
  33.     bool initBox2D();  
  34. //    设置物体    密度为10  
  35.     void addBodyForSprite(B2Sprite *sprite,double density=10.0);  
  36. //    设置夹具   密度为10  
  37.     void addFixtureForSprite(B2Sprite *sprite,double density=10.0);  
  38. //此方法用于销毁死亡对象,因为物体不可以则碰撞检测方法中直接销毁,可以中updata函数最后执行  
  39.     void dealCollisions();  
  40.   
  41. //    碰撞检测方法 开始重叠  
  42.     virtual void BeginContact(b2Contact *contact);  
  43. //    结束重叠  
  44.     virtual void EndContact(b2Contact *contact);  
  45. //    对应碰撞处理对前后时间点  
  46. //    virtual void ProSolve(b2Contact *contact,const b2Manifold *oldManifold);  
  47. //    virtual void PostSolve(b2Contact *contact,const b2ContactImpulse *impulse);  
  48.       
  49.     static Box2dHandler* handler();  
  50.     bool init();  
  51.     void draw();  
  52.     void update(float dt);  
  53. //    void removeSprite(B2Sprite *node);  
  54. //    CC_SYNTHESIZE(Box2dHandlerDe, , )  
  55. };  

Box2dHandler.cpp

[cpp]  view plain copy
  1. #include "Box2dHandler.h"  
  2. //把Box2dHandler设置成单例  
  3. Box2dHandler* Box2dHandler::handler()  
  4. {  
  5.     static Box2dHandler *handler=NULL;  
  6.     if(handler==NULL)  
  7.     {  
  8.         handler=new Box2dHandler();  
  9.         handler->init();  
  10.         return handler;  
  11.     }  
  12.     else  
  13.         return handler;  
  14. }  
  15.   
  16. //Box2dHandler初始化  
  17. bool Box2dHandler::init()  
  18. {  
  19.     this->initBox2D();  
  20.     this->scheduleUpdate();  
  21.       
  22.  //    GLESDebugDraw m_debugDraw(PTM_RATIO);  
  23. //    调试绘图  
  24.     m_debugDraw=new GLESDebugDraw(PTM_RATIO);  
  25.       
  26.     uint32 flags=0;  
  27.     flags+=b2Draw::e_shapeBit;  
  28.     m_debugDraw->SetFlags(flags);  
  29.     m_world->SetDebugDraw(m_debugDraw);  
  30.     return true;  
  31. }  
  32. //初始化物理引擎  
  33. bool Box2dHandler::initBox2D()  
  34. {  
  35.     CCSize s=CCDirector::sharedDirector()->getWinSize();  
  36. //    设置物理世界中的重力xy。  
  37.     b2Vec2 gravity;  
  38.     gravity.Set(0.0f, -1.0f);  
  39.     m_world=new b2World(gravity);  
  40. //    允许睡眠,可以提高物体的处理效率,只有中受到物理效果影响时才会唤醒对象  
  41.     m_world->SetAllowSleeping(true);  
  42. //    开启连续物理测试  
  43. //    连续物理测试会使物理模拟时间间隔缩短,提高模拟精度,避免速度较快的两个物体直接穿透  
  44. //    但该方法同样会降低引擎但运行性能  
  45.     m_world->SetContinuousPhysics(true);  
  46. //    设置碰撞事件的监听器  
  47.     m_world->SetContactListener(this);  
  48. //    定义一个边界范围,存在碰撞效果  
  49.     b2BodyDef groundBodyDef;  
  50.     groundBodyDef.position.Set(0, 0);  
  51.       
  52.     b2Body *groundBody=m_world->CreateBody(&groundBodyDef);  
  53. //    定义边缘形状  
  54.     b2EdgeShape groundBox;  
  55. //    底部  
  56.     groundBox.Set(b2Vec2(0,0), b2Vec2(s.width/PTM_RATIO,0));  
  57.     groundBody->CreateFixture(&groundBox,0);  
  58. //    顶部  
  59.     groundBox.Set(b2Vec2(0,s.height/PTM_RATIO), b2Vec2(s.width/PTM_RATIO,s.height/PTM_RATIO));  
  60.     groundBody->CreateFixture(&groundBox,0);  
  61. //    左侧  
  62.     groundBox.Set(b2Vec2(0,s.height/PTM_RATIO), b2Vec2(0,0));  
  63.     groundBody->CreateFixture(&groundBox,0);  
  64. //    右侧  
  65.     groundBox.Set(b2Vec2(s.width/PTM_RATIO,s.height/PTM_RATIO), b2Vec2(s.width/PTM_RATIO,0));  
  66.     groundBody->CreateFixture(&groundBox,0);  
  67.       
  68.       
  69.     return true;  
  70. }  
  71. //为物理世界但精灵添加夹具  
  72.  void Box2dHandler::addFixtureForSprite(B2Sprite *sprite,double density)  
  73. {  
  74. //    定义形状,多边形  
  75.     b2PolygonShape spriteShape;  
  76. //    得到精灵的大小  
  77.     CCSize size =sprite->getContentSize();  
  78.     spriteShape.SetAsBox(size.width/PTM_RATIO/2, size.height/PTM_RATIO/2);  
  79. //    创建一个夹具的对象  
  80.     b2FixtureDef spriteShapeDef;  
  81. //    设置夹具的形状  
  82.     spriteShapeDef.shape=&spriteShape;  
  83. //    设置夹具的密度  
  84.     spriteShapeDef.density=density;  
  85. //  设置精灵物理世界的“物体”的夹具  
  86.     b2Body *spriteBody=sprite->getB2Body();  
  87.     spriteBody->CreateFixture(&spriteShapeDef);  
  88. }  
  89. //为物理世界的精灵创建Box2D物体  
  90. void Box2dHandler::addBodyForSprite(B2Sprite *sprite,double density)  
  91. {  
  92. //  创建一个物体对象  
  93.     b2BodyDef spriteBodyDef;  
  94. //    物体对象--b2Body  
  95. //    静态物体(b2_staticBody)。质量为 0,不可以移动,通常模拟我们游戏的物理边  
  96. //    界:大地、墙壁等。  
  97. //    平台物体(b2_kinematicBody)。按照固定路线运动的物体,比如说电梯,运动的  
  98. //    滚梯,运行的火车等等。  
  99. //    动态物体(b2_dynamicBody)。我们最常见的精灵对象对应的物体。  
  100. //    物体类型为动态物体  
  101.     spriteBodyDef.type=b2_dynamicBody;  
  102.       
  103.     spriteBodyDef.position.Set((sprite->getPosition().x)/PTM_RATIO, (sprite->getPosition().y)/PTM_RATIO);  
  104. //    设置用户数据,允许存放一个任意类型的指针向我们自定义的数据  
  105. //    用于将物体与游戏程序关联起来,所有物体的用完数据应指向相同的数据类型  
  106.     spriteBodyDef.userData=sprite;  
  107. //    在物理世界中创建物体  
  108.     b2Body *spriteBody=m_world->CreateBody(&spriteBodyDef);  
  109. //    为精灵添加物体  
  110.     sprite->setB2Body(spriteBody);  
  111. //    为精灵添加夹具  
  112.     this->addFixtureForSprite(sprite,density);  
  113. }  
  114. //   更新状态  
  115.  void Box2dHandler::update(float dt)  
  116. {  
  117. //    遍历物理世界中的物体  
  118.     for(b2Body *b=m_world->GetBodyList();b;b=b->GetNext())  
  119.     {  
  120. //        是否没有精灵数据  
  121.         if(b->GetUserData()!=NULL)  
  122.         {  
  123.               
  124.             B2Sprite *sprite =static_cast<B2Sprite*>(b->GetUserData());  
  125. //            b2Vec2 pos=b->GetPosition();  
  126. //            b2Vec2 bPosition=b2Vec2(pos.x+sprite->getPosition().x/PTM_RATIO,pos.y+sprite->getPosition().y/PTM_RATIO);  
  127. //            sprite->setPosition(ccp(pos.x*PTM_RATIO+sprite->getPosition().x,pos.y*PTM_RATIO+sprite->getPosition().y));  
  128. //            float32 bAngle=-CC_DEGREES_TO_RADIANS(sprite->getRotation());  
  129. //            b->SetTransform(bPosition, bAngle);  
  130. //       //     sprite->setRotation(-b->GetAngle()/0.01745329252f);  
  131.             sprite->setPosition(ccp(b->GetPosition().x*PTM_RATIO,b->GetPosition().y*PTM_RATIO));  
  132.             sprite->setRotation(-CC_RADIANS_TO_DEGREES(b->GetAngle()));  
  133.         }  
  134.     }  
  135. //    Box世界的刷新接口,第一个参数为更新引擎的间隔时间,第二个参数为计算速度,第三个参数为位置时迭代的次数  
  136.     m_world->Step(dt, 8, 8);  
  137.     //this->dealCollisions();  
  138. }  
  139. //使调试绘图显示到屏幕上  
  140. void Box2dHandler::draw()  
  141. {  
  142.     CCNode::draw();  
  143. //    保存opengl绘图状态  
  144.     ccGLEnableVertexAttribs(kCCVertexAttribFlag_Position);  
  145. //    用kmGLPushMatrix函数来保存状态  
  146.     kmGLPushMatrix();  
  147. //    绘制调试图案  
  148.     m_world->DrawDebugData();  
  149. //    用kmGLPopMatrix函数来恢复状态  
  150.     kmGLPopMatrix();  
  151.       
  152. }  
  153. void Box2dHandler::BeginContact(b2Contact *contact)  
  154. {  
  155.     printf("开始碰撞");  
  156. }  
  157. void Box2dHandler::EndContact(b2Contact *contact)  
  158. {  
  159.     printf("结束碰撞");  
  160. }  
测试代码:

[cpp]  view plain copy
  1. //    获取可视区域大小  
  2.     CCSize visibleSize = CCDirector::sharedDirector()->getVisibleSize();  
  3. //    获取可视区域左下角坐标  
  4.     CCPoint origin = CCDirector::sharedDirector()->getVisibleOrigin();  
  5. //    创建物理世界  
  6.     Box2dHandler *handler =Box2dHandler::handler();  
  7.     this->addChild(handler);  
  8.   
  9.     B2Sprite* pSprite =new B2Sprite();  
  10.     pSprite->initWithFile("CloseNormal.png");  
  11.     pSprite->setPosition(ccp(visibleSize.width/2 + origin.x, visibleSize.height/1.1 + origin.y));  
  12.     handler->addBodyForSprite(pSprite);  
  13.       
  14.     B2Sprite* pSprite2 =new B2Sprite();  
  15.     pSprite2->initWithFile("CloseNormal.png");  
  16.     pSprite2->setPosition(ccp(visibleSize.width/2 + origin.x, visibleSize.height/6 + origin.y));  
  17.     handler->addBodyForSprite(pSprite2);  
  18.       
  19.     this->addChild(pSprite);  
  20.     this->addChild(pSprite2);  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值