Cocos2d-X Box2D的使用实例

1、PhysicsSprite类

(1)PhysicsSprite.h

#include <iostream>

#include "Box2D/Box2D.h"

#include "cocos2d.h"

USING_NS_CC;

class PhysicsSprite:publicCCSprite

{

public:

    PhysicsSprite();

    void setPhysicsBody(b2Body *boddy);

    int hp;//血量

private:

    b2Body * m_pBody;

};


(2)PhysicsSprite.cpp

#include "PhysicsSprite.h"

PhysicsSprite::PhysicsSprite():m_pBody(NULL)

{

//0与1之间的随机数

    int idx=(CCRANDOM_0_1()>0.5?0:1);

    int idy=(CCRANDOM_0_1()>0.5?0:1);

    this->initWithFile("blocks.png",CCRectMake(32*idx, 32*idy, 32, 32));

    hp=5;

}

void PhysicsSprite::setPhysicsBody(b2Body *boddy)

{

    m_pBody=boddy;

}


2、MyContactListener

(1)MyContactListener.h

#include <iostream>

#include "cocos2d.h"

#include "Box2D.h"

USING_NS_CC;

class MyContactListener:publicb2ContactListener

{

public:

    CCLayer *_layer;

    b2World *_world;

    MyContactListener();

    ~MyContactListener();

    MyContactListener(b2World *w,CCLayer *c);

    

    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);

};


(2)MyContactListener.cpp

#include "MyContactListener.h"

#include "PhysicsSprite.h"

MyContactListener::MyContactListener()

{

}

MyContactListener::~MyContactListener()

{

}

MyContactListener::MyContactListener(b2World *w,CCLayer *c)

{

    _world=w;

    _layer=c;

}

//两个物体重叠时

void MyContactListener::BeginContact(b2Contact* contact)

{

    CCLog("BeginContact!");

}

//两个物体分离时

void MyContactListener::EndContact(b2Contact* contact)

{

    CCLog("EndContact!");

}

void MyContactListener::PreSolve(b2Contact* contact,const b2Manifold* oldManifold)

{

    CCLog("PreSolve!");

}

void MyContactListener::PostSolve(b2Contact* contact,const b2ContactImpulse* impulse)

{

    CCLog("PostSolve!");

    float force=impulse->normalImpulses[0];

    if(force>2)

    {

        PhysicsSprite *spriteA=(PhysicsSprite *)contact->GetFixtureA()->GetBody()->GetUserData();

        PhysicsSprite *spriteB=(PhysicsSprite *)contact->GetFixtureB()->GetBody()->GetUserData();

        if(spriteA && spriteB)

        {

           

            spriteA->hp--;

            spriteB->hp--;

        }

    }

}

3、b2World

(1)b2World.h

#include <iostream>

#include "Box2D.h"

#include "cocos2d.h"

USING_NS_CC;


class World:public CCLayer

{

public:

    virtual bool init();

    static CCScene *scene();

    CREATE_FUNC(World);

    

    void update(float dt);

    void initPhysical();

    void addNewSpriteAtPosition(CCPoint position);

    

    virtual bool ccTouchBegan(CCTouch *pTouch,CCEvent *pEvent);

    virtual void ccTouchMoved(CCTouch *pTouch,CCEvent *pEvent);

    virtual void ccTouchEnded(CCTouch *pTouch,CCEvent *pEvent);

    

    CCLabelTTF *label1;

    CCLabelTTF *label2;

private:

    b2World *world;

    

};


(2)b2World.cpp

#include "b2World.h"

#include "PhysicsSprite.h"

#include "MyContactListener.h"


CCScene *World::scene()

{

    CCScene *scene=CCScene::create();

    World *w=World::create();

    scene->addChild(w);

    return scene;

}

 bool World::init()

{

    if(!CCLayer::init())

    {

        return false;

    }

    //CCDirector::sharedDirector()->getTouchDispatcher()->addTargetedDelegate(this, 0, true);

    

   

    label1=CCLabelTTF::create("0","Arial", 30);

    label1->setPosition(ccp(240,160));

    this->addChild(label1);

    

    

    initPhysical();

    

    MyContactListener *listener=newMyContactListener(world,this);

    world->SetContactListener(listener);

    this->setTouchEnabled(true);

    this->setTouchMode(kCCTouchesOneByOne);

    

    

    this->scheduleUpdate();

    return true;

}

void World::update(float dt)

{

    int velocityIteration=8;//8次速度

    int positionIteration=1;//一次位置

    world->Step(dt, velocityIteration, positionIteration);

    

    b2Body *b=world->GetBodyList();

    while(b)

    {

        b2Body *p=b;

        b=b->GetNext();

        if(p->GetUserData() !=NULL)

        {

            PhysicsSprite *myActor=(PhysicsSprite *)p->GetUserData();

            if(myActor->hp<0)

            {

                myActor->removeFromParent();

                world->DestroyBody(p);

            }

            myActor->setPosition(CCPointMake(p->GetPosition().x*32, p->GetPosition().y*32));

            myActor->setRotation(-1*CC_RADIANS_TO_DEGREES(p->GetAngle()));

        }

    }

    /*

    for(b2Body *b=world->GetBodyList();b;b->GetNext() )

    {

        if(b->GetUserData() != NULL)

        {

            PhysicsSprite *myActor=(PhysicsSprite *)b->GetUserData();

            if(myActor->hp<0)

            {

                myActor->removeFromParent();

                world->DestroyBody(b);

            }

            myActor->setPosition(CCPointMake(b->GetPosition().x*32, b->GetPosition().y*32));

            myActor->setRotation(-1*CC_RADIANS_TO_DEGREES(b->GetAngle()));

        }

    }

     */

}

//初始化

void World::initPhysical()

{

    CCSize winSize=CCDirector::sharedDirector()->getWinSize();

    b2Vec2 gravity;//设置重力(结构体)

    gravity.Set(0.0f, -10.0f);

    //创建世界

    world=new b2World(gravity);

    world->SetAllowSleeping(true);//设置睡眠

    world->SetContinuousPhysics(true);//设置连续碰撞

    //创建刚体(结构体)

    b2BodyDef groundBodyDef;

    groundBodyDef.position.Set(0.0f,0.0f);

    b2Body *groundBody=world->CreateBody(&groundBodyDef);

     //创建形状(结构体)

    b2EdgeShape groundBox;

    //bottom

    groundBox.Set(b2Vec2(0,0), b2Vec2(winSize.width/32,0));

    groundBody->CreateFixture(&groundBox,0);

    //top

    groundBox.Set(b2Vec2(0, winSize.height/32),b2Vec2(winSize.width/32,winSize.height/32));

    groundBody->CreateFixture(&groundBox,0);

    //left

    groundBox.Set(b2Vec2(0,0), b2Vec2(0,winSize.height/32));

    groundBody->CreateFixture(&groundBox,0);

    //right

    groundBox.Set(b2Vec2(winSize.width/32,0), b2Vec2(winSize.width/32,winSize.height/32));

    groundBody->CreateFixture(&groundBox,0);//填充

}


void World::addNewSpriteAtPosition(CCPoint position)

{

    PhysicsSprite *sprite=newPhysicsSprite();

    sprite->setPosition(position);

    this->addChild(sprite);

    

    b2BodyDef bodyDef;//创建刚体

    bodyDef.type=b2_dynamicBody;//设置类型

    bodyDef.position.Set(position.x/32, position.y/32);

    bodyDef.userData=sprite;//刚体与精灵链接

    

    b2Body *body=world->CreateBody(&bodyDef);

    b2PolygonShape dynamicBox;//多边形

    dynamicBox.SetAsBox(0.5f,0.5f);//指定形状为长方形

    b2FixtureDef fixtureDef;//关联

    fixtureDef.shape=&dynamicBox;//形状

    fixtureDef.density=10.0f;//密度

    fixtureDef.friction=0.0f;//摩擦

    

    fixtureDef.restitution=1.0f;//恢复

    body->CreateFixture(&fixtureDef);//刚体创建夹具

    sprite->setPhysicsBody(body);

}


bool World::ccTouchBegan(CCTouch *pTouch,CCEvent *pEvent)

{

    return true;

}

void World::ccTouchMoved(CCTouch *pTouch,CCEvent *pEvent)

{


}

void World::ccTouchEnded(CCTouch *pTouch,CCEvent *pEvent)

{

    this->addNewSpriteAtPosition(pTouch->getLocation());

}

注意:

 1、b2BodyDef与b2FixtureDef的区别:

    //b2BodyDef是用来存放刚体在世界中的数据,比如position(x,y) , angle 等等属性。

   // b2FixtureDef则是用来存放刚体自身的数据,比如shape(polygonShape,等等),density,friction等等属性。

2、step方法要传递三个参数,dt,velocityIterations, positionIterations:

即world->Step(dt, velocityIteration, positionIteration):

  dt,时步。通常建议设置为1/60,这样的话你的fps最好也设置到60。但是我发现更好的办法就是把timeStep设置为fps的倒数即可。如果你的fps是30,那么就设置为1/30。

 (1)velocityIterations,速度迭代

 (2) positionIterations,位置迭代: 这两个值通常建议设置为10,更低的迭代值会让你牺牲一些准确性,相反的为你的程序提升一部分性能。





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值