重写Cocos2d-x 3.0游戏开发实战详解的Box2D案例

很遗憾,看完该案例后无法正常运行,检查代码后,判断PhyObject里面的Sprite显示是缺失的,是时候重写一个了。


1、建立一个基本PhyObject class,描述物体的基本属性:

enum SHAPE{
    
    Rect,Circle,Polygon
    
};


class PhyObject{
    
public:
    
    bool _isStatic;
    float _density;
    float _friction;
    float _restitution;
    float* _shapeData;
    SHAPE _shape;
    Sprite* _sprite;
    b2Body* _body;
    void fresh();
    
};

Cpp文件里,描述一个重要的方法,sprite随着物理模型的移动而移动:

void PhyObject::fresh(){
    
    //CCLog("fresh");
    Size visibleSize = Director::getInstance()->getVisibleSize();
    Point origin = Director::getInstance()->getVisibleOrigin();
    
    b2Vec2 position=this->_body->GetPosition();
    float angle=this->_body->GetAngle();


    this->_sprite->setPosition
    (
     Point
     (
      position.x,
      position.y
      )
     );
  
    this->_sprite->setRotation(-angle*180.0/3.1415926);
}

2、建立一个基本的矩形物理类:

RectPhyObject* RectPhyObject::create(bool isStatic,float* mShapeData,Layer* layer,b2World* world,float density,float friction,float restitution,std::string pic){
    
    RectPhyObject* rectObject=new RectPhyObject;


    b2BodyDef bodyDef;
    if(!isStatic)
    {
        bodyDef.type = b2_dynamicBody;
    }
    bodyDef.position.Set(mShapeData[0], mShapeData[1]);
    rectObject->_body = world->CreateBody(&bodyDef);
    //body->SetUserData(id);
    
    b2PolygonShape dynamicBox;
    dynamicBox.SetAsBox(mShapeData[2], mShapeData[3]);
    
    if(!isStatic)
    {
        b2FixtureDef fixtureDef;
        fixtureDef.shape = &dynamicBox;
        fixtureDef.density = density;
        fixtureDef.friction = friction;
        fixtureDef.restitution=restitution;
        rectObject->_body->CreateFixture(&fixtureDef);
    }
    else
    {
        rectObject->_body->CreateFixture(&dynamicBox, 0.0f);
    }
    
    rectObject->_sprite = Sprite::create(pic);
    layer->addChild(rectObject->_sprite, 1);
    Size size=rectObject->_sprite->getContentSize();


    float pw=mShapeData[2]*2;
    float ph=mShapeData[3]*2;
    float scaleX=pw/size.width;
    float scaleY=ph/size.height;
    rectObject->_sprite->setScaleX(scaleX);
    rectObject->_sprite->setScaleY(scaleY);
    rectObject->_sprite->setPosition(mShapeData[0],mShapeData[1]);
    
    


    return rectObject;
}

以上可以根据该物体是否是静态,决定密度、摩擦、回复系数的值,边框也是用这个类来生成的。

3、用于碰撞的圆形物理类:

CirclePhyObject* CirclePhyObject::create(bool isStatic,float* mShapeData,Layer* layer,b2World* world,float density,float friction,float restitution,std::string pic){

    b2CircleShape dynamicCircle;
    dynamicCircle.m_radius=mShapeData[2];
    //dynamicBox.SetAsBox(mShapeData[2], mShapeData[3]);
    
    if(!isStatic)
    {
        b2FixtureDef fixtureDef;
        fixtureDef.shape = &dynamicCircle;
 

只有shape会不同,只要设置半径就好。

4、看下主游戏界面:

static int* NUMS=new int[9]{1,2,3,4,5,4,3,2,1};
static std::string SA[8]={
"pic/brownCube.png","pic/pinkCube.png",
"pic/redCube.png","pic/yellowCube.png",
"pic/greenCube.png","pic/blueCube.png",
"pic/violetCube.png","pic/orangeCube.png"
};

被碰撞的物体序列和图片来源;

bool HelloWorld::init()
{
    if ( !Layer::init() )
    {
        return false;
    }
    schedule(schedule_selector(HelloWorld::update), 0.001f);
    Size visibleSize = Director::getInstance()->getVisibleSize();
    Vec2 origin = Director::getInstance()->getVisibleOrigin();
    LayerColor *background = LayerColor::create( Color4B(255,255,255,255) );
    this->addChild(background,-20);


    b2Vec2 gravity(0.0f, -10.0f);
    world = new b2World(gravity);
    world->SetAllowSleeping(true);


    setGround();
    createPyramid();
    createBullet();
    
    return true;
}


分别创建框架、被碰撞的物体系列、用于碰撞的物体;记得要注册帧时间方法(该方法内要调用物体的fresh方法);


void HelloWorld::setGround(){
    
    Size visibleSize = Director::getInstance()->getVisibleSize();
    Vec2 origin = Director::getInstance()->getVisibleOrigin();
    
    auto data1=new float[4]{20,450,10,400};
    auto object1=RectPhyObject::create(true,data1,this,world, 0, 0, 0, "pic/bolckGrayCube.png");
    index=0;
    indexStr=new std::string(StringUtils::format("%d", index));
    pom[*indexStr]=object1;
    
    auto data2=new float[4]{visibleSize.width-20,450,10,400};
    auto object2=RectPhyObject::create(true,data2,this,world, 0, 0, 0, "pic/bolckGrayCube.png");
    index++;
    indexStr=new std::string(StringUtils::format("%d", index));
    pom[*indexStr]=object2;
    
    auto data3=new float[4]{visibleSize.width/2,50,visibleSize.width/2-10,10};
    auto object3=RectPhyObject::create(true,data3,this,world, 0, 0, 0, "pic/bolckGrayCube.png");
    index++;
    indexStr=new std::string(StringUtils::format("%d", index));
    pom[*indexStr]=object3;
    
    CCLog("_MAP length is: %d",pom.size());
}

pom是存储所有物体的map集合;框架里都是静态物体;

void HelloWorld::createPyramid(){
    
    for(int i=0;i<9;i++)
    {
        for(int j=0;j<NUMS[i];j++){
            
            float x=80+i*60;
            float y=100+j*60;
            auto data=new float[4]{x,y,10,30};
            index++;
            indexStr=new std::string(StringUtils::format("%d", index));
            auto object=RectPhyObject::create(false,data,this,world, 0.6f, 0.1f, 0.2f, SA[index%8]);
            pom[*indexStr]=object;
            CCLog("set i: %d, j: %d,index: %d",i,j,index);
        }
    }
    
}

创建物体系列,分成9排,每排数量由数组MUNS决定,创建的都是动态物体.

void HelloWorld::createBullet(){
    
    auto data=new float[4]{250,800,20,20};
    index++;
    indexStr=new std::string(StringUtils::format("%d", index));
    auto object=CirclePhyObject::create(false,data,this,world, 2.6f, 0.1f, 0.2f, "pic/ball.png");
    pom[*indexStr]=object;
    CCLog("set index: %d",index);


}

创建掉下来的球形物体;

void HelloWorld::update(float dt){
    
    //CCLOG("update");
    step();
    std::map<std::string,PhyObject*>::iterator iter;
    for(iter=pom.begin();iter!=pom.end();iter++)
    {
        PhyObject* po=iter->second;
        po->fresh();
    }
}

好了,加入帧时间动作,物体就都动起来了!


最后小结下,原书里因该是遗漏了sprite的位置信息,供大家参考。

源码:https://github.com/frank1982/Box2DDemo

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值