box2d创建简单的入门示例:

实现功能:

1.实现刚体的创建

2.能够创建自定义的精灵刚体

3.精灵之间的相互碰撞

工具的使用:

要创建一个 自定义的刚体精灵(不规则形状),就要用到一个工具PhysicalEditor,下载地址:http://yun.baidu.com/share/link?shareid=1782518146&uk=1209145999&third=0
我们将图片添加到工程中,但要确保图片精灵周围是透明的才行,然后选择Exporter->Box2D generic(PLIST),最后直接publish就可以了,然后将plist文件和原图片资源一起导入到工程的Resource下。

操作步骤:

1.导入外部的GLES-Render类

2.主场景类:

class QueryCallback : public b2QueryCallback { public:     b2Vec2 m_point;     b2Fixture * m_fixture;          QueryCallback(const b2Vec2 & point)     {         m_point = point;         m_fixture = NULL;     }     bool ReportFixture(b2Fixture * fixture)     {         b2Body * body = fixture->GetBody();         if (body->GetType() == b2_dynamicBody)         {             bool inside = fixture->TestPoint(m_point);             if(inside)             {                 m_fixture = fixture;                 return false;             }         }         return true;     }      };  class SecondScene : public CCLayer { public:     ~SecondScene();     SecondScene();      static CCScene* scene();          void initPhysics();     void addNewSpriteAtPosition(CCPoint p);          virtual void draw();     void update(float dt);          void ccTouchesBegan(CCSet *pTouches, CCEvent *pEvent);     void ccTouchesMoved(CCSet *pTouches, CCEvent *pEvent);     void ccTouchesEnded(CCSet* touches, CCEvent* event);          bool MouseDown(const b2Vec2 & p);     void MouseMove(const b2Vec2 & p);     void MouseUp();      private:     GLESDebugDraw * m_debugDraw;     b2World * world;     CCTexture2D * m_pSpriteTexture;     b2MouseJoint * m_mouseJoint;  //鼠标关节节点     b2Body * m_groundBody; }; #endif /* defined(__box2dDemo__SecondHelloScene__) */


cpp

#include "SecondHelloScene.h" #include "SimpleAudioEngine.h" #include "GLES-Render.h" #include "GB2ShapeCache-x.h" #include "ContactListener.h" //碰撞检测 using namespace cocos2d; using namespace CocosDenshion;  #define PTM_RATIO 32  enum {     kTagParentNode = 1, };  //PhysicsSprite::PhysicsSprite() //: m_pBody(NULL) //{ //     //} // //void PhysicsSprite::setPhysicsBody(b2Body * body) //{ //    m_pBody = body; //} // //bool PhysicsSprite::isDirty(void) //{ //    return true; //} // //// returns the transform matrix according the Chipmunk Body values //CCAffineTransform PhysicsSprite::nodeToParentTransform(void) //{ //    b2Vec2 pos  = m_pBody->GetPosition(); //     //    float x = pos.x * PTM_RATIO; //    float y = pos.y * PTM_RATIO; //     //    if ( isIgnoreAnchorPointForPosition() ) { //        x += m_obAnchorPointInPoints.x; //        y += m_obAnchorPointInPoints.y; //    } //     //    // Make matrix //    float radians = m_pBody->GetAngle(); //    float c = cosf(radians); //    float s = sinf(radians); //     //    if( ! m_obAnchorPointInPoints.equals(CCPointZero) ){ //        x += c*-m_obAnchorPointInPoints.x + -s*-m_obAnchorPointInPoints.y; //        y += s*-m_obAnchorPointInPoints.x + c*-m_obAnchorPointInPoints.y; //    } //     //    // Rot, Translate Matrix //    m_sTransform = CCAffineTransformMake( c,  s, //                                         -s,    c, //                                         x,    y ); //     //    return m_sTransform; //}  SecondScene::SecondScene() {     setTouchEnabled( true );     setAccelerometerEnabled( true );          CCSize s = CCDirector::sharedDirector()->getWinSize();     this->initPhysics();          addNewSpriteAtPosition(ccp(s.width / 2, s.height / 2));      //    CCSpriteBatchNode *parent = CCSpriteBatchNode::create("blocks.png", 100); //    m_pSpriteTexture = parent->getTexture(); //     //    addChild(parent, 0, kTagParentNode); //     //     //    addNewSpriteAtPosition(ccp(s.width/2, s.height/2)); //     //    CCLabelTTF *label = CCLabelTTF::create("Tap screen", "Marker Felt", 32); //    addChild(label, 0); //    label->setColor(ccc3(0,0,255)); //    label->setPosition(ccp( s.width/2, s.height-50));          scheduleUpdate(); }  SecondScene::~SecondScene() {     delete world;     world = NULL;          //delete m_debugDraw; }  void SecondScene::initPhysics() {     //添加自定义的精灵     GB2ShapeCache::sharedGB2ShapeCache()->addShapesWithFile("zhizhu.plist");          CCSize s = CCDirector::sharedDirector()->getWinSize();          b2Vec2 gravity;     gravity.Set(0.0f, -10.0f);     world = new b2World(gravity);          b2BodyDef bodydef;     m_groundBody = world->CreateBody(&bodydef);          world->SetAllowSleeping(true);          world->SetContinuousPhysics(false);//隧道效应,穿透,true表示不能穿透               //接触监听,碰撞检测     b2ContactListener *contactListener = new ContactListener();     world->SetContactListener(contactListener);          //静态刚体     m_debugDraw = new GLESDebugDraw( PTM_RATIO );     world->SetDebugDraw(m_debugDraw);          uint32 flags = 0;     flags += b2Draw::e_shapeBit;     //        flags += b2Draw::e_jointBit;     //        flags += b2Draw::e_aabbBit;     //        flags += b2Draw::e_pairBit;     //        flags += b2Draw::e_centerOfMassBit;     m_debugDraw->SetFlags(flags);               // Define the ground body.     b2BodyDef groundBodyDef;     groundBodyDef.position.Set(5, 1);           b2Body* groundBody = world->CreateBody(&groundBodyDef);          // Define the ground box shape.     b2EdgeShape groundBox;          // bottom          groundBox.Set(b2Vec2(0,0), b2Vec2(s.width/PTM_RATIO,0));     groundBody->CreateFixture(&groundBox,0);          // top     groundBox.Set(b2Vec2(0,s.height/PTM_RATIO), b2Vec2(s.width/PTM_RATIO,s.height/PTM_RATIO));     groundBody->CreateFixture(&groundBox,0);          // left     groundBox.Set(b2Vec2(0,s.height/PTM_RATIO), b2Vec2(0,0));     groundBody->CreateFixture(&groundBox,0);          // right     groundBox.Set(b2Vec2(s.width/PTM_RATIO,s.height/PTM_RATIO), b2Vec2(s.width/PTM_RATIO,0));     groundBody->CreateFixture(&groundBox,0); }  void SecondScene::draw() {     CCLayer::draw();          ccGLEnableVertexAttribs( kCCVertexAttribFlag_Position );          kmGLPushMatrix();          world->DrawDebugData();          kmGLPopMatrix(); }  void SecondScene::addNewSpriteAtPosition(CCPoint p) {               string name = "alien";     CCSprite * sprite = CCSprite::create((name + ".png").c_str());     sprite->setPosition(p);     this->addChild(sprite);      //    CCSprite * sp = CCSprite::create("Icon.png"); //    sp->setPosition(CCPointMake(100, 100)); //    this->addChild(sp);          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);               // Define another box shape for our dynamic body.     //通过vertexHelper工具生成多边形     b2PolygonShape dynamicBox; //    b2Vec2 verts[] = { //        b2Vec2(-12.8f / PTM_RATIO, 50.9f / PTM_RATIO), //        b2Vec2(-48.8f / PTM_RATIO, 2.3f / PTM_RATIO), //        b2Vec2(-30.7f / PTM_RATIO, -37.9f / PTM_RATIO), //        b2Vec2(28.8f / PTM_RATIO, -18.9f / PTM_RATIO), //        b2Vec2(30.8f / PTM_RATIO, 16.9f / PTM_RATIO), //        b2Vec2(20.8f / PTM_RATIO, 44.9f / PTM_RATIO) //    }; //    dynamicBox.Set(verts, 6);     //dynamicBox.SetAsBox(.5f, .5f);//These are mid points for our 1m box           //    b2FixtureDef fixtureDef; //    fixtureDef.shape = &dynamicBox; //    fixtureDef.density = 1.0f;//密度 //    fixtureDef.friction = 0.3f;//摩擦 //    fixtureDef.restitution = 0.5f;//恢复,也可看成弹性系数 //     //     //    body->CreateFixture(&fixtureDef);          GB2ShapeCache * sc = GB2ShapeCache::sharedGB2ShapeCache();     sc->addFixturesToBody(body, name);     sprite->setAnchorPoint(sc->anchorPointForShape(name)); }   void SecondScene::update(float dt) {     int velocityIterations = 8;     int positionIterations = 1;      world->Step(dt, velocityIterations, positionIterations);      for (b2Body* b = world->GetBodyList(); b; b = b->GetNext())     {         if (b->GetUserData() != NULL) {             //Synchronize the AtlasSprites position and rotation with the corresponding body             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()) );//CC_RADIANS_TO_DEGREES弧度转角度         }     } }  CCScene* SecondScene::scene() {     // 'scene' is an autorelease object     CCScene *scene = CCScene::create();          // add layer as a child to scene     CCLayer* layer = new SecondScene();     scene->addChild(layer);     layer->release();          return scene; }  void SecondScene::ccTouchesBegan(cocos2d::CCSet *pTouches, cocos2d::CCEvent *pEvent) {     CCSetIterator it;     CCTouch * touch;     for(it = pTouches->begin(); it != pTouches->end(); it++)     {         touch = (CCTouch *)(*it);         if(!touch)             break;         CCPoint location = touch->getLocation();                  if(!this->MouseDown(b2Vec2(location.x / PTM_RATIO, location.y / PTM_RATIO)))         {             this->addNewSpriteAtPosition(location);         }     } }  void SecondScene::ccTouchesMoved(cocos2d::CCSet *pTouches, cocos2d::CCEvent *pEvent) {     CCSetIterator it;     CCTouch * touch;     for(it = pTouches->begin(); it != pTouches->end(); it++)     {         touch = (CCTouch *)(*it);         if(!touch)             break;         CCPoint location = touch->getLocation();                  this->MouseMove(b2Vec2(location.x / PTM_RATIO,location.y / PTM_RATIO));     } }  void SecondScene::ccTouchesEnded(CCSet* touches, CCEvent* event) {     CCSetIterator it;     CCTouch* touch;          for( it = touches->begin(); it != touches->end(); it++)     {         touch = (CCTouch*)(*it);              if(!touch)             break;              CCPoint location = touch->getLocationInView();              location = CCDirector::sharedDirector()->convertToGL(location);              addNewSpriteAtPosition( location );     }     this->MouseUp(); }  bool SecondScene::MouseDown(const b2Vec2 &p) {     if(m_mouseJoint != NULL)     {         return false;     }          b2AABB aabb;     b2Vec2 d;     d.Set(0.001f, 0.001f);     aabb.lowerBound = p - d;     aabb.upperBound = p + d;          QueryCallback callback(p);          world->QueryAABB(&callback, aabb);          if (callback.m_fixture)     {         b2Body * body = callback.m_fixture->GetBody();         b2MouseJointDef md;         md.bodyA = m_groundBody;  //m_groundBody需要在上面init方法里定义一下         md.bodyB = body;         md.target = p;         md.maxForce = 1000.0f * body->GetMass();         m_mouseJoint = (b2MouseJoint *)world->CreateJoint(&md);         body->SetAwake(true);         return true;     }          return true; }  void SecondScene::MouseMove(const b2Vec2 &p) {     if(m_mouseJoint)     {         m_mouseJoint->SetTarget(p);     } }  void SecondScene::MouseUp() {     if(m_mouseJoint)     {         world->DestroyJoint(m_mouseJoint);         m_mouseJoint = NULL;     } }


3.碰撞检测类(ContactListener)

#ifndef __box2dDemo__ContactListener__ #define __box2dDemo__ContactListener__  //碰撞检测 #include   #include "cocos2d.h" #include "Box2D.h"  using namespace cocos2d;  class ContactListener : public b2ContactListener {     void BeginContact(b2Contact * contact);     void EndContact(b2Contact *contact); };  #endif /* defined(__box2dDemo__ContactListener__) */

cpp

#include "ContactListener.h"  void ContactListener::BeginContact(b2Contact *contact) {     b2Body *bodyA = contact->GetFixtureA()->GetBody();     b2Body *bodyB = contact->GetFixtureB()->GetBody();     CCSprite *spriteA = (CCSprite *)bodyA->GetUserData();     CCSprite *spriteB = (CCSprite *)bodyB->GetUserData();          if (spriteA != NULL && spriteB != NULL) {         spriteA->setColor(ccMAGENTA);         spriteB->setColor(ccMAGENTA);     } }  void ContactListener::EndContact(b2Contact *contact) {     b2Body *bodyA = contact->GetFixtureA()->GetBody();     b2Body *bodyB = contact->GetFixtureB()->GetBody();     CCSprite *spriteA = (CCSprite *)bodyA->GetUserData();     CCSprite *spriteB = (CCSprite *)bodyB->GetUserData();          if (spriteA != NULL && spriteB != NULL) {         spriteA->setColor(ccWHITE);         spriteB->setColor(ccWHITE);     } }


运行效果:

[cocos2d-x]box2d的简单应用_第1张图片

[cocos2d-x]box2d的简单应用_第2张图片


cocos2d-x游戏开发QQ交流群:280818155

备注:加入者必须修改:地区-昵称,很少有动态的将定期清理