AKever

导航

Cocos2dx(1) Box2d Demo

Box2d 介绍:http://www.cnblogs.com/TS-qrt/articles/Box2DEx.html

链接参考:http://www.cnblogs.com/andyque/archive/2011/05/27/2059453.html

       http://www.cnblogs.com/andyque/archive/2011/05/27/2059460.html

 为了创建一个body对象,你需要做很多事情--首先,创建一个body定义结构,然后是body对象,再指定一个shap,再是fixture定义,然后再创建一个fixture对象。下面会一个一个解释刚刚这些东西。

  1. 你首先创建一个body定义结构体,用以指定body的初始属性,比如位置或者速度。
  2. 一旦创建好body结构体后,你就可以调用world对象来创建一个body对象了。
  3. 然后,你为body对象定义一个shape,用以指定你想要仿真的物体的几何形状。
  4. 接着创建一个fixture定义,同时设置之前创建好的shape为fixture的一个属性,并且设置其它的属性,比如质量或者摩擦力。
  5. 最后,你可以使用body对象来创建fixture对象,通过传入一个fixture的定义结构就可以了。
  6. 请注意,你可以往单个body对象里面添加很多个fixture对象。这个功能在你创建特别复杂的对象的时候非常有用。比如自行车,你可能要创建2个轮子,车身等等,这些fixture可以用关节连接起来。

b2BodyDef:

b2BodyDef.type=b2Body.b2_staticBody 是默认值,表示静态的对象;
b2BodyDef.type=b2Body.b2_dynamicBody; 当无这句而设置质量 b2FixtureDef.density=1时 表示其质量为0,也就是说他是静态不能动的物体;
当有“b2BodyDef.type=b2Body.b2_dynamicBody”这一句时,b2FixtureDef.density=1 表示其质量为1,即没有这句时质量为0,有了这一句才可以自己设置动态对象的质量.

b2BodyDef bodyDef;

ballBodyDef.type = b2_dynamicBody;  //表示非静态对象
bodyDef.position.Set(0.0f, 4.0f); //确定位置 bodyDef.userData = &myActor; //数据 bodyDef.angle = 0.25f * b2_pi; //旋转角度

b2FixtureDef fixtureDef; 

fixtureDef.shape = &dynamicBox; //形状
fixtureDef.density = 1.0f;  //密度
fixtureDef.friction = 0.3f;  //摩擦
fixtureDef.userData = myData;  //数据
fixtureDef.restitution =0.8f;
// 回复力。它的范围也是0到1.0. 0意味着对象碰撞之后不会反弹,1意味着是完全弹性碰撞,会以同样的速度反弹。

 

Demo

|-GLES-Render.h/cpp (Box2d测试调用,引擎自带,具体查看以上链接)
|-HelloWorldScene.h/cpp

GLES-Render.h

/*
* Copyright (c) 2006-2007 Erin Catto http://www.gphysics.com
*
* iPhone port by Simon Oliver - http://www.simonoliver.com - http://www.handcircus.com
*
* This software is provided 'as-is', without any express or implied
* warranty.  In no event will the authors be held liable for any damages
* arising from the use of this software.
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*/
#ifndef RENDER_H
#define RENDER_H
#include "Box2D/Box2D.h"
#include "cocos2d.h"
struct b2AABB;
// This class implements debug drawing callbacks that are invoked
// inside b2World::Step.
class GLESDebugDraw : public b2Draw
{
    float32 mRatio;
    cocos2d::CCGLProgram* mShaderProgram;
    GLint        mColorLocation;
    void initShader( void );
public:
    GLESDebugDraw();
    GLESDebugDraw( float32 ratio );
    virtual void DrawPolygon(const b2Vec2* vertices, int vertexCount, const b2Color& color);
    virtual void DrawSolidPolygon(const b2Vec2* vertices, int vertexCount, const b2Color& color);
    virtual void DrawCircle(const b2Vec2& center, float32 radius, const b2Color& color);
    virtual void DrawSolidCircle(const b2Vec2& center, float32 radius, const b2Vec2& axis, const b2Color& color);
    virtual void DrawSegment(const b2Vec2& p1, const b2Vec2& p2, const b2Color& color);
    virtual void DrawTransform(const b2Transform& xf);
    virtual void DrawPoint(const b2Vec2& p, float32 size, const b2Color& color);
    virtual void DrawString(int x, int y, const char* string, ...); 
    virtual void DrawAABB(b2AABB* aabb, const b2Color& color);
};
#endif

GLES-Render.cpp

/*
 * Copyright (c) 2006-2007 Erin Catto http://www.gphysics.com
 *
 * iPhone port by Simon Oliver - http://www.simonoliver.com - http://www.handcircus.com
 *
 * This software is provided 'as-is', without any express or implied
 * warranty.  In no event will the authors be held liable for any damages
 * arising from the use of this software.
 * Permission is granted to anyone to use this software for any purpose,
 * including commercial applications, and to alter it and redistribute it
 * freely, subject to the following restrictions:
 * 1. The origin of this software must not be misrepresented; you must not
 * claim that you wrote the original software. If you use this software
 * in a product, an acknowledgment in the product documentation would be
 * appreciated but is not required.
 * 2. Altered source versions must be plainly marked as such, and must not be
 * misrepresented as being the original software.
 * 3. This notice may not be removed or altered from any source distribution.
 */
#include "GLES-Render.h"
#include "cocos2d.h"
#include <stdio.h>
#include <stdarg.h>
#include <string.h>

USING_NS_CC;

GLESDebugDraw::GLESDebugDraw()
    : mRatio( 1.0f )
{
    this->initShader();
}

GLESDebugDraw::GLESDebugDraw( float32 ratio )
    : mRatio( ratio )
{
    this->initShader();
}

void GLESDebugDraw::initShader( void )
{
    mShaderProgram = CCShaderCache::sharedShaderCache()->programForKey(kCCShader_Position_uColor);
    mColorLocation = glGetUniformLocation( mShaderProgram->getProgram(), "u_color");
}

void GLESDebugDraw::DrawPolygon(const b2Vec2* old_vertices, int vertexCount, const b2Color& color)
{
    mShaderProgram->use();
    mShaderProgram->setUniformsForBuiltins();
    b2Vec2* vertices = new b2Vec2[vertexCount];
    for( int i=0;i<vertexCount;i++) 
    {
        vertices[i] = old_vertices[i];
        vertices[i] *= mRatio;
    }
    mShaderProgram->setUniformLocationWith4f(mColorLocation, color.r, color.g, color.b, 1);
    glVertexAttribPointer(kCCVertexAttrib_Position, 2, GL_FLOAT, GL_FALSE, 0, vertices);
    glDrawArrays(GL_LINE_LOOP, 0, vertexCount);
    CC_INCREMENT_GL_DRAWS(1);
    CHECK_GL_ERROR_DEBUG();
    delete[] vertices;
}

void GLESDebugDraw::DrawSolidPolygon(const b2Vec2* old_vertices, int vertexCount, const b2Color& color)
{
    mShaderProgram->use();
    mShaderProgram->setUniformsForBuiltins();
    b2Vec2* vertices = new b2Vec2[vertexCount];
    for( int i=0;i<vertexCount;i++) {
        vertices[i] = old_vertices[i];
        vertices[i] *= mRatio;
    }    
    mShaderProgram->setUniformLocationWith4f(mColorLocation, color.r*0.5f, color.g*0.5f, color.b*0.5f, 0.5f);
    glVertexAttribPointer(kCCVertexAttrib_Position, 2, GL_FLOAT, GL_FALSE, 0, vertices);
    glDrawArrays(GL_TRIANGLE_FAN, 0, vertexCount);
    mShaderProgram->setUniformLocationWith4f(mColorLocation, color.r, color.g, color.b, 1);
    glDrawArrays(GL_LINE_LOOP, 0, vertexCount);
    CC_INCREMENT_GL_DRAWS(2);
    CHECK_GL_ERROR_DEBUG();
    delete[] vertices;
}

void GLESDebugDraw::DrawCircle(const b2Vec2& center, float32 radius, const b2Color& color)
{
    mShaderProgram->use();
    mShaderProgram->setUniformsForBuiltins();
    const float32 k_segments = 16.0f;
    int vertexCount=16;
    const float32 k_increment = 2.0f * b2_pi / k_segments;
    float32 theta = 0.0f;
    GLfloat*    glVertices = new GLfloat[vertexCount*2];
    for (int i = 0; i < k_segments; ++i)
    {
        b2Vec2 v = center + radius * b2Vec2(cosf(theta), sinf(theta));
        glVertices[i*2]=v.x * mRatio;
        glVertices[i*2+1]=v.y * mRatio;
        theta += k_increment;
    }
    mShaderProgram->setUniformLocationWith4f(mColorLocation, color.r, color.g, color.b, 1);
    glVertexAttribPointer(kCCVertexAttrib_Position, 2, GL_FLOAT, GL_FALSE, 0, glVertices);
    glDrawArrays(GL_LINE_LOOP, 0, vertexCount);
    CC_INCREMENT_GL_DRAWS(1);
    CHECK_GL_ERROR_DEBUG();
    delete[] glVertices;
}

void GLESDebugDraw::DrawSolidCircle(const b2Vec2& center, float32 radius, const b2Vec2& axis, const b2Color& color)
{
    mShaderProgram->use();
    mShaderProgram->setUniformsForBuiltins();
    const float32 k_segments = 16.0f;
    int vertexCount=16;
    const float32 k_increment = 2.0f * b2_pi / k_segments;
    float32 theta = 0.0f;
    GLfloat*    glVertices = new GLfloat[vertexCount*2];
    for (int i = 0; i < k_segments; ++i)
    {
        b2Vec2 v = center + radius * b2Vec2(cosf(theta), sinf(theta));
        glVertices[i*2]=v.x * mRatio;
        glVertices[i*2+1]=v.y * mRatio;
        theta += k_increment;
    }
    mShaderProgram->setUniformLocationWith4f(mColorLocation, color.r*0.5f, color.g*0.5f, color.b*0.5f, 0.5f);
    glVertexAttribPointer(kCCVertexAttrib_Position, 2, GL_FLOAT, GL_FALSE, 0, glVertices);
    glDrawArrays(GL_TRIANGLE_FAN, 0, vertexCount);

    mShaderProgram->setUniformLocationWith4f(mColorLocation, color.r, color.g, color.b, 1);
    glDrawArrays(GL_LINE_LOOP, 0, vertexCount);

    // Draw the axis line
    DrawSegment(center,center+radius*axis,color);
    CC_INCREMENT_GL_DRAWS(2);
    CHECK_GL_ERROR_DEBUG();
    delete[] glVertices;
}

void GLESDebugDraw::DrawSegment(const b2Vec2& p1, const b2Vec2& p2, const b2Color& color)
{
    mShaderProgram->use();
    mShaderProgram->setUniformsForBuiltins();
    mShaderProgram->setUniformLocationWith4f(mColorLocation, color.r, color.g, color.b, 1);
    GLfloat    glVertices[] = 
    {
        p1.x * mRatio, p1.y * mRatio,
        p2.x * mRatio, p2.y * mRatio
    };
    glVertexAttribPointer(kCCVertexAttrib_Position, 2, GL_FLOAT, GL_FALSE, 0, glVertices);
    glDrawArrays(GL_LINES, 0, 2);
    CC_INCREMENT_GL_DRAWS(1);
    CHECK_GL_ERROR_DEBUG();
}

void GLESDebugDraw::DrawTransform(const b2Transform& xf)
{
    b2Vec2 p1 = xf.p, p2;
    const float32 k_axisScale = 0.4f;
    p2 = p1 + k_axisScale * xf.q.GetXAxis();
    DrawSegment(p1, p2, b2Color(1,0,0));

    p2 = p1 + k_axisScale * xf.q.GetYAxis();
    DrawSegment(p1,p2,b2Color(0,1,0));
}

void GLESDebugDraw::DrawPoint(const b2Vec2& p, float32 size, const b2Color& color)
{
    mShaderProgram->use();
    mShaderProgram->setUniformsForBuiltins();
    mShaderProgram->setUniformLocationWith4f(mColorLocation, color.r, color.g, color.b, 1);
    //    glPointSize(size);
    GLfloat glVertices[] = {
        p.x * mRatio, p.y * mRatio
    };
    glVertexAttribPointer(kCCVertexAttrib_Position, 2, GL_FLOAT, GL_FALSE, 0, glVertices);
    glDrawArrays(GL_POINTS, 0, 1);
    //    glPointSize(1.0f);
    CC_INCREMENT_GL_DRAWS(1);
    CHECK_GL_ERROR_DEBUG();
}

void GLESDebugDraw::DrawString(int x, int y, const char *string, ...)
{
//    NSLog(@"DrawString: unsupported: %s", string);
    //printf(string);
    /* Unsupported as yet. Could replace with bitmap font renderer at a later date */
}
void GLESDebugDraw::DrawAABB(b2AABB* aabb, const b2Color& color)
{
    mShaderProgram->use();
    mShaderProgram->setUniformsForBuiltins();
    mShaderProgram->setUniformLocationWith4f(mColorLocation, color.r, color.g, color.b, 1);
    GLfloat                glVertices[] = {
        aabb->lowerBound.x * mRatio, aabb->lowerBound.y * mRatio,
        aabb->upperBound.x * mRatio, aabb->lowerBound.y * mRatio,
        aabb->upperBound.x * mRatio, aabb->upperBound.y * mRatio,
        aabb->lowerBound.x * mRatio, aabb->upperBound.y * mRatio
    };
    glVertexAttribPointer(kCCVertexAttrib_Position, 2, GL_FLOAT, GL_FALSE, 0, glVertices);
    glDrawArrays(GL_LINE_LOOP, 0, 8);
    CC_INCREMENT_GL_DRAWS(1);
    CHECK_GL_ERROR_DEBUG();
}

HelloWorldScene.h

#ifndef __HELLOWORLD_SCENE_H__
#define __HELLOWORLD_SCENE_H__

#include "cocos2d.h"
#include "Box2D\Box2D.h"

class HelloWorld : public cocos2d::CCLayer
{
public:
    // Here's a difference. Method 'init' in cocos2d-x returns bool, instead of returning 'id' in cocos2d-iphone
    virtual bool init();  

    // there's no 'id' in cpp, so we recommend returning the class instance pointer
    static cocos2d::CCScene* scene();
    
    // a selector callback
    void menuCloseCallback(CCObject* pSender);
    
    // implement the "static node()" method manually
    CREATE_FUNC(HelloWorld);
private:
    b2World *m_pWorld;
    b2Body *m_pBody;
    cocos2d::CCSprite *m_pBall;

    virtual void draw();  //DebugDraw
    void update(float dt);
};

#endif // __HELLOWORLD_SCENE_H__

HelloWorldScene.cpp

#include "HelloWorldScene.h"

#include "GLES-Render.h"
#define PTM_RATIO 32.0 //像素/米

USING_NS_CC;

CCScene* HelloWorld::scene()
{
    // 'scene' is an autorelease object
    CCScene *scene = CCScene::create();
    
    // 'layer' is an autorelease object
    HelloWorld *layer = HelloWorld::create();

    // add layer as a child to scene
    scene->addChild(layer);

    // return the scene
    return scene;
}

// on "init" you need to initialize your instance
bool HelloWorld::init()
{
    // 1. super init first
    if ( !CCLayer::init() )
    {
        return false;
    }  
    CCSize visibleSize = CCDirector::sharedDirector()->getVisibleSize();
//create a back_ball(circle)
    m_pBall = CCSprite::create("box2d/back_ball.png"); 
    this->addChild(m_pBall);//box2d
        //create a world ------------------------------
    b2Vec2 gravity = b2Vec2(0.0f, -9.8f);
    m_pWorld = new b2World(gravity);
    m_pWorld->SetAllowSleeping(true); //允许睡觉,允许睡眠,可以提高物理世界中物体的处理效率,只有在发生碰撞时才唤醒该对象
    m_pWorld->SetContinuousPhysics(true); //开启连续物理测试

        //create a ground
    b2BodyDef groundBodyDef; //1
    groundBodyDef.position.Set(0, 0);
    b2Body *groundBody = m_pWorld->CreateBody(&groundBodyDef); //2
    b2EdgeShape groundShape; //3
    b2FixtureDef groundFixtureDef;
    groundFixtureDef.shape = &groundShape;
            //4 bottom
    groundShape.Set(b2Vec2(0,0), b2Vec2(visibleSize.width/PTM_RATIO, 0));
    groundBody->CreateFixture(&groundFixtureDef);
            //  left
    groundShape.Set(b2Vec2(0,0), b2Vec2(0, visibleSize.height/PTM_RATIO));
    groundBody->CreateFixture(&groundFixtureDef);
            //  up
    groundShape.Set(b2Vec2(0, visibleSize.height/PTM_RATIO), b2Vec2(visibleSize.width/PTM_RATIO, visibleSize.height/PTM_RATIO));
    groundBody->CreateFixture(&groundFixtureDef);
            //  right
    groundShape.Set(b2Vec2(visibleSize.width/PTM_RATIO, visibleSize.height/PTM_RATIO), b2Vec2(visibleSize.width/PTM_RATIO, 0));
    groundBody->CreateFixture(&groundFixtureDef);

        //create a body circle --------------------------------
            //1.b2BodyDef
    b2BodyDef ballBodyDef;    //创建一个body定义结构体
    ballBodyDef.position.Set(8, visibleSize.height*0.8f/PTM_RATIO);
    ballBodyDef.type = b2_dynamicBody;  //表示非静态Body,受重力影响
    ballBodyDef.userData = m_pBall;   //将CCSprite作为userData存入bodyDef中,在update定时器中处理
            //2.b2Body
    b2Body *ballBody = m_pWorld->CreateBody(&ballBodyDef);
            //3. b2CircleShape && b2FixtureDef
    b2CircleShape ballShape;
    b2FixtureDef ballFixtureDef;  //刚体材质属性和形状等,
    ballFixtureDef.density = 1.0f; //密度
    ballFixtureDef.friction = 0.2f; //摩擦力
    ballFixtureDef.restitution = 0.8f; //回复力,影响弹性系数
    ballFixtureDef.shape = &ballShape;    //形状
    ballShape.m_radius = m_pBall->getContentSize().width*0.5f/PTM_RATIO;
    ballBody->CreateFixture(&ballFixtureDef);

    //================================
    //DebugDraw
    GLESDebugDraw* m_pDebugDraw = new GLESDebugDraw(PTM_RATIO);
    m_pWorld->SetDebugDraw(m_pDebugDraw);
    uint32 flags = 0;
    flags += b2Draw::e_shapeBit;   
    m_pDebugDraw->SetFlags(flags);

    this->scheduleUpdate();

    return true;
}


void HelloWorld::menuCloseCallback(CCObject* pSender)
{
#if (CC_TARGET_PLATFORM == CC_PLATFORM_WINRT) || (CC_TARGET_PLATFORM == CC_PLATFORM_WP8)
    CCMessageBox("You pressed the close button. Windows Store Apps do not implement a close button.","Alert");
#else
    CCDirector::sharedDirector()->end();
#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
    exit(0);
#endif
#endif
}

//DebugDraw
void HelloWorld::draw()
{
    CCNode::draw();

    ccGLEnableVertexAttribs(kCCVertexAttribFlag_Position);
    kmGLPushMatrix();
    m_pWorld->DrawDebugData();
    kmGLPopMatrix();
}

void HelloWorld::update(float dt)
{
    int32 velocityIterations = 8;
    int32 positionIterations = 2;
    /*Box2d是通过定期调用step来更新动画的,第一个参数为时间步,第二个
        参数是速度迭代次数,推荐8次,第三个参数是位置迭代*/ 
    m_pWorld->Step(dt, velocityIterations, positionIterations);
    for(b2Body* b=m_pWorld->GetBodyList();b;b=b->GetNext())
    {
        if(b->GetUserData() != NULL) 
        {    
            CCSprite* ballData = (CCSprite*)b->GetUserData();
            ballData->setPosition(ccp(b->GetPosition().x*PTM_RATIO, 
                b->GetPosition().y*PTM_RATIO));
            ballData->setRotation(-1*CC_RADIANS_TO_DEGREES(b->GetAngle()));
        }
    }
}

 

End, thank you!!

posted on 2014-01-27 12:50  AKever  阅读(1044)  评论(0)    收藏  举报