cocos2d-x中的Box2D物理引擎

在Cocos2d-x中集成了2个物理引擎,一个是Chipmunk,一个是Box2D。前者是用C语言编写的,文档和例子相对较少;Box2D是用C++写的,并且有比较完善的文档和资料。所以在需要使用物理引擎的时候,大多数开发者会选择Box2D。Box2D是一款用来模拟刚体在物理世界运动的仿真引擎。通过Box2D物理引擎,世界中的物体就可以按照运动定律进行运动。

注:Box2D下的类都是以b2为前缀的,希望不要与你的命名相冲突

1. 首先我们介绍下需要用到的基本概念。

世界(world) :世界代表了一个遵循物理规律的空间,所有的物体都在世界中运动,世界具有创建销毁刚体,创建销毁关节等功能

刚体(body) :一块十分坚硬的物质,它上面的任何两点之间的距离都是完全不变的。刚体具体划分为静态刚体,动态刚体和棱柱刚体(漂浮刚体)

形状(shape):一块严格依附于刚体(body)的 2D 碰撞几何结构(collision geometry)。形状通过关联附加到刚体上,这样刚体就具备了视觉上的外形。

关节(joint):它是一种用于把两个或多个物体固定到一起的约束。Box2D 支持的关节类型有:旋转,棱柱,距离等等。关节可以支持限制(limits)和马达(motors)

关节限制(joint limit):一个关节限制(joint limit)限定了一个关节的运动范围。例如人类的胳膊肘只能做某一范围角度的运动

关节马达(joint motor):一个关节马达能依照关节的自由度来驱动所连接的物体。例如,你可以使用一个马达来驱动一个肘的旋转

2. 我们现在来简单的使用下Box2D,体验一下模拟的物理世界

(1)首先需要创建世界,创建世界需要两个步骤,首先生成重力向量,然后根据重力向量生成世界

bool HelloWorld::init()

{

if ( !CCLayer::init() )

{

return false;

}

// b2Vec2带的两个参数是表示x,y方向的重力大小,正负表示方向

b2Vec2 gravity(0.0f,-10.0f);

// 创建Box2D的世界

world = new b2World(gravity);

// 设置刚体休眠(当刚体到达边界的时候,停止对刚体的计算,节约CPU)

world->SetAllowSleeping(true);

// 使用连续的物理检测

world->SetContinuousPhysics(true);

// 注册碰撞检测的监听

world->SetContactListener(this);

// 创建漂浮刚体

addBird(1, 3.33, b2_kinematicBody);

// 创建静态刚体

addGrass(5.0, 0.5, b2_staticBody);

// 设置屏幕可以触摸

setTouchEnabled(true);

// 开辟线程回调模拟

this->scheduleUpdate();

return true;

}

(2)创建非静态刚体

void HelloWorld::addBird(float x,float y,b2BodyType objectType)
{
    /*****   构建刚体的参数(包括位置,类型)   *****/

    // 定义刚体用到的精灵
    CCSprite *sprite = CCSprite::create("bird.png");
    addChild(sprite);

    // 配置刚体的定义(类似隐形,没有肉体的刚体)
    b2BodyDef def;
    def.position = b2Vec2(x, y); // 设置位置
    def.type = objectType; // 配置刚体的类型,分为三类:静态刚体,漂浮刚体,动态刚体
    if (objectType == b2_kinematicBody) {
        def.linearVelocity = b2Vec2(2, 0); // 两个参数分别代表横向速度和纵向速度
    }

    // 定义形状(此处为多边形)
    b2PolygonShape birdShape;
    // 定义边界(世界边界),参数是半宽,半高,因为生成的大小是其传入参数的2倍
    birdShape.SetAsBox(sprite->getContentSize().width / RATIO / 2, sprite->getContentSize().height / RATIO / 2);

    // 配置刚体的体积(材料(有肉的实体))
    b2FixtureDef fixtureDef;
    fixtureDef.density = 1; // 密度
    fixtureDef.friction = 0.3; // 摩擦因数
    fixtureDef.restitution = 0.8f; // 反弹效果
    fixtureDef.shape = &birdShape; // 配置刚体的实体

    /*****    构建刚体的形体    *****/

    // 创建刚体
    birdBody = world->CreateBody(&def);

    // 将材料加入到刚体里
    birdBody->CreateFixture(&fixtureDef);

    // 绑定精灵到刚体
    birdBody->SetUserData(sprite);
}

(3) 添加静态刚体

void HelloWorld::addGrass(float x,float y,b2BodyType objectType)
{
    /*****   构建刚体的参数(包括位置,类型)   *****/

    // 定义刚体用到的精灵
    CCSprite *sprite = CCSprite::create("grass.png");
    addChild(sprite,1);

    // 配置刚体的定义(类似隐形,没有肉体的刚体)
    b2BodyDef def;
    def.position = b2Vec2(x, y); // 设置位置
    def.type = objectType; // 配置刚体的类型,分为三类:静态刚体,漂浮刚体,动态刚体

    // 定义形状(此处为多边形)
    b2PolygonShape grassShape;
    // 定义边界(世界边界),参数是半宽,半高,因为生成的大小是其传入参数的2倍
    grassShape.SetAsBox(sprite->getContentSize().width / RATIO / 2 , sprite->getContentSize().height / RATIO / 2);

    // 配置刚体的体积(材料(有肉的实体))
    b2FixtureDef fixtureDef;
    fixtureDef.density = 1;
    fixtureDef.friction = 0.3;
    fixtureDef.shape = &grassShape; // 配置刚体的实体

    /*****    构建刚体的形体    *****/

    // 创建刚体
    grassBody = world->CreateBody(&def);

    // 将材料加入到刚体里
    grassBody->CreateFixture(&fixtureDef);

    // 绑定精灵到刚体
    grassBody->SetUserData(sprite);

}

(4)驱动模拟世界

// 世界类用于驱动模拟
void HelloWorld::update(float a)
{
    float32 timeStep = 1.0f / 60.f;
    // Step()函数的第一个参数是时间步数,后面两个参数分别是速度阶段和位置阶段
    world->Step(timeStep, 8, 3);

    CCSprite *s;

    for (b2Body *b = world->GetBodyList(); b; b = b->GetNext()) {
        if (b->GetUserData() != NULL) {
            s = (CCSprite*)b->GetUserData();            // 漂浮刚体的运动模拟
            s->setPosition(ccp(b->GetPosition().x * RATIO, b->GetPosition().y * RATIO));
            if (s->getPosition().x < -10 || s->getPosition().x > 490 || s->getPosition().y < -10) {
                this->removeChild(s);
                world->DestroyBody(b);
            }
        }
    }
}

(5)设置屏幕可以触摸,实现触摸屏幕添加刚体的效果

void HelloWorld::registerWithTouchDispatcher(void)
{
    CCDirector::sharedDirector()->getTouchDispatcher()->addTargetedDelegate(this, 1, false);
}
bool HelloWorld::ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent)
{
    CCPoint p = pTouch->getLocation();

    addBird(p.x / RATIO, p.y / RATIO, b2_dynamicBody);

    return true;
}

(6)让HelloWorld类继承b2ContactListener,重写BeginContact函数,实现刚体的检测碰撞

// 碰撞检测
void HelloWorld::BeginContact(b2Contact* contact)
{
    if ((contact->GetFixtureA()->GetBody() == grassBody || contact->GetFixtureB()->GetBody() == grassBody)) {
        CCLog("有鸟落在草地上!");
    } else {
        CCLog("鸟与鸟之间发生碰撞");
    }
}

效果如图所示:

时间: 2024-11-04 07:43:42

cocos2d-x中的Box2D物理引擎的相关文章

实例介绍Cocos2d-x中Box2D物理引擎:HelloBox2D

我们通过一个实例介绍一下,在Cocos2d-x 3.x中使用Box2D物理引擎的开发过程,熟悉这些API的使用.这个实例运行后的场景如图所示,当场景启动后,玩家可以触摸点击屏幕,每次触摸时候,就会在触摸点生成一个新的精灵,精灵的运行自由落体运动. HelloBox2D实例 使用Box2D引擎进行开发过程,如图12-15所示.下面我们就按照这个步骤介绍一下代码部分.首先看一下看HelloWorldScene.h文件,它的代码如下: [html] view plaincopy #ifndef __H

实例介绍Cocos2d-x中Box2D物理引擎:碰撞检测

在Box2D中碰撞事件通过实现b2ContactListener类函数实现,b2ContactListener是Box2D提供的抽象类,它的抽象函数:virtual void BeginContact(b2Contact* contact).两个物体开始接触时会响应,但只调用一次.virtual void EndContact(b2Contact* contact).分离时响应.但只调用一次.virtual void PreSolve(b2Contact* contact, const b2Ma

实例介绍Cocos2d-x中Box2D物理引擎:碰撞检測

在Box2D中碰撞事件通过实现b2ContactListener类函数实现,b2ContactListener是Box2D提供的抽象类,它的抽象函数:virtual void BeginContact(b2Contact* contact).两个物体開始接触时会响应,但仅仅调用一次. virtual void EndContact(b2Contact* contact).分离时响应. 但仅仅调用一次. virtual void PreSolve(b2Contact* contact, const

COCOS2DX学习之box2d物理引擎在VS2012中的配置

因为vs中并没有继承box2dz游戏物理引擎,所以在开发有关box2d的游戏的时候,要自己将这个引擎添加进去.首先在解决方案中添加一个已经存在的项目,这个项目的路径就是你创建的cocos2dx项目的目录里面cocos2d\external\Box2D\proj.win32这个文件夹下面的一个vs工程,把它添加进去编译好,就会看到proj.win32\Debug.win32中有了Box2d的库. 之后,将生成的box2d的库添加到项目属性的连接器中即可 tool是我创建的coocs2dx项目 CO

实例介绍Cocos2d-x中Box2D物理引擎:使用关节

下面我们将使用Box2D物理引擎技术进行重构.使得关节能够掌握如何在Box2D使用关节约束.HelloWorldScene.cpp中与使用关节的相关代码如下: [html] view plaincopy void HelloWorld::addNewSpriteAtPosition(Vec2 p) { log("Add sprite %0.2f x %02.f",p.x,p.y); //创建物理引擎精灵对象A auto spriteA = Sprite::create("Bo

瘸腿蛤蟆笔记36-cocos2d-x-3.2 Box2d物理引擎Ray-cast使用

瘸腿蛤蟆原创笔记,欢迎转载,转载请标明出处: 上篇回顾 本篇名言:人类心灵深处,有许多沉睡的力量:唤醒这些人们从未梦想过的力量,巧妙运用,便能彻底改变一生.[澳瑞森·梅伦] 上几篇中,蛤蟆学习了Box2d物理引擎中如何将我们创建的物理体给描绘在程序里面.让我们能够看到一个非常直观的物体,便于后续进一步学习和理解. 具体步骤 我们还是使用helloworld工程. 1.  首先将\cocos2d-x-3.2\tests\cpp-tests\Classes\Box2DTestBed目录中的6个文件G

python下的Box2d物理引擎的配置

/******************************* I come back! 由于已经大四了,正在找工作 导致了至今以来第二长的时间内没有更新博客.向大家表示道歉 *******************************/ 前言 Box2d物理引擎 Box2d是一款开源的2d物理引擎,存在很多的版本,C++,Java,html5和python等等 著名的愤怒的小鸟就是使用了这款物理引擎进行开发的 目前也有很多的2d游戏引擎内置了对Box2d物理引擎的支持,比如cocos2d,

【极客学院出品】Cocos2d-X系列课程之九-BOX2D物理引擎

Cocos2d-x 是时下最热门的手游引擎,在国内和国外手机游戏开发使用的份额各自是70%和25%,在App Store的top10中,有7个是用它开发的. 本节课程为Cocos2d-x系列课程之九,学习BOX2D物理引擎! 学习路径图: 课程适合小白系统学习,仅需6个课时,在极客学院首席讲师风趣幽默的课程里轻松掌握BOX2D物理引擎.恭喜你也从此将走上为牛X程序员的不归路. 今年上午9点正式上线,请别再期待娱乐圈的新闻了,马上開始学习吧>>> 我们还有很多其它更新更实战的课程,登录极客

COCOS2DX学习之Box2d物理引擎使用之------动态物体的创建

1.创建一个物理世界 首先要引入一个头文件#include "Box2D\Box2D.h" 之后利用b2word创建一个对象,并且指定这个物理世界中的加速度方向. word = new b2World(b2Vec2(0,-10));                        //指定物理世界的加速度 最后还要重写一下update函数,这个函数在之前的计时器学习的时候已经说过,每一帧的变动都将自动执行这个函数.所以我们要通过这个函数来进行创建的物理世界的刷新. 2.创建一个运动的物体