#include <Box2D/Box2D.h>
一个 b2FixtureDef 是依附在刚体 身上的物理特质的属性
一个刚体 有多个 b2FixtureDef
每一个 b2FixtureDef 又有形状shape、密度、摩擦系数等成员属性
创建一个漂浮的物体,不受重力影响,向右漂浮动
addRectBody(1,5,b2_kinematicBody);
#pragma mark - 添加一个刚体 // 添加一个静止的或运动的Rect刚体,通过参数type指定,x和y是世界坐标中的位置 void Box2DScene::addRectBody(float x, float y, b2BodyType body_type) { // 1.1 结构体b2BodyDef // 每个刚体都有自身的 固有的 必须的 b2BodyDef属性 b2BodyDef def; // 在世界坐标中 的位置:第x米,第y米处 def.position = b2Vec2(x, y); // 设置【b2BodyDef】的 类型 (运动的或静止的或漂浮的) def.type = body_type; // 设置【b2BodyDef】的 线速度 y = 10 ,表示物体向上飞 if(body_type == b2_dynamicBody){ // 动态物体 自由落体 def.linearVelocity = b2Vec2(0, 9.8); }else{ // 漂浮物体 向右飘动 def.linearVelocity = b2Vec2(1, 0); } // 设置【b2BodyDef】的 子弹效应 (防止碰撞检测时 由于速度 太快,而失效;如本应反弹,结果陷入地板内) // def.bullet = true; // 1.2 通过调用world的方法,创建一个Body物体 // 参数 是一个 b2BodyDef,它是构造一个刚体必须的、固有的东东 // 因为,每个刚体都有自身的 b2BodyDef属性 b2Body* body = world->CreateBody(&def); // ************************************************* // 2.1 形状分为 圆和多边形 b2PolygonShape shape; shape.SetAsBox(0.5, 0.5); // 2.2 一个刚体 有多个 b2FixtureDef // 一个 b2FixtureDef 是依附在刚体 身上的物理物质的属性 // 每一个 b2FixtureDef 又有形状shape、密度、摩擦系数等成员属性 b2FixtureDef fixtureDef; // 每一个 b2FixtureDef都有一个成员shape fixtureDef.shape = &shape; // 密度 fixtureDef.density = 1; // 摩擦系数 fixtureDef.friction = 0.3; // 为刚体 添加一个 b2FixtureDef body->CreateFixture(&fixtureDef); // ************************************************* // 3、创建并添加一个 cocos2d 的精灵 auto s = Sprite::create(); // 0.5是物理世界中的精灵大小 单位是 米 // 即在物理世界中,精灵 是一个1米 * 1米的方块 s->setTextureRect(Rect(0, 0, 0.5*2*RATIO, 0.5*2*RATIO)); // 添加到图层Layer addChild(s); // ************************************************* // 4、绑定 cocos2d界面上的精灵 body->SetUserData(s); }
#pragma mark - 添加一个地板 void Box2DScene::addGroundBody() { // 1.1 结构体b2BodyDef // 每个刚体都有自身的 固有的 必须的 b2BodyDef属性 b2BodyDef def; // 在世界坐标中 的位置:第x米,第y米处 这个是在 log("宽:%f",winSize.width); // 位置 def.position = b2Vec2(480/RATIO,0); // 设置【b2BodyDef】的 类型 (运动的或静止的或漂浮的) def.type = b2_staticBody; // 1.2 通过调用world的方法,创建一个Body物体 // 参数 是一个 b2BodyDef,它是构造一个刚体必须的、固有的东东 // 因为,每个刚体都有自身的 b2BodyDef属性 groundBody = world->CreateBody(&def); // ************************************************* // 2.1 形状分为 圆和多边 b2PolygonShape groundShape; // 尺寸: 在物理世界中的 半长和 半宽 多少米 groundShape.SetAsBox(480/RATIO, 0.5); // 2.2 一个刚体 有多个 b2FixtureDef // 一个 b2FixtureDef 是依附在刚体 身上的物理物质的属性 // 每一个 b2FixtureDef 又有形状shape、密度、摩擦系数等成员属性 b2FixtureDef fixureDef; // 形状 fixureDef.shape = &groundShape; // 密度 fixureDef.density = 1; // 摩擦系数 fixureDef.friction = 0.3; groundBody->CreateFixture(&fixureDef); }
首先, 设置碰撞检测 的侦听者 为当前Layer
world->SetContactListener(this);
virtual void BeginContact(b2Contact* contact);
contact->GetFixtureA()->GetBody()
// // Box2DScene.h // 01_cocos2d-x // // Created by beyond on 14-10-5. // // #ifndef ___1_cocos2d_x__Box2DScene__ #define ___1_cocos2d_x__Box2DScene__ #include "cocos2d.h" // 1、导入物理世界 主头文件 #include <Box2D/Box2D.h> USING_NS_CC; // 注意 这儿,继承的是 Layer // 要想进行碰撞检测,必须 实现接口 class Box2DScene : public cocos2d::Layer,public b2ContactListener { private: // 2、成员变量:物理世界,参数 指定x和y的重力方向 b2World *world; // 因为 要碰撞检测,所以 b2Body *groundBody; // 屏幕尺寸 Size winSize; public: // c++里面没有id类型, 所以 返回类的实例对象的 指针 static cocos2d::Scene* createScene(); // 以下是 不同点:cocos2d-x的 'init' 方法 返回 bool // 而cocos2d-iphone 返回 'id' 类型 virtual bool init(); // 宏 自动实现 "静态的 create()方法" CREATE_FUNC(Box2DScene); // 4、在时钟方法里,模拟世界的运行 step virtual void update(float dt); // 5、添加一个静止的或运动的Rect刚体,通过参数type指定,x和y是世界坐标中的位置 void addRectBody(float x,float y,b2BodyType body_type); // 6、添加一个地板 void addGroundBody(); // 7、碰撞检测 // 接口中的方法,是一个固定定法 virtual void BeginContact(b2Contact* contact); }; #endif /* defined(___1_cocos2d_x__Box2DScene__) */
// // Box2DScene.cpp // 01_cocos2d-x // // Created by beyond on 14-10-5. // // #include "Box2DScene.h" // cocos2d 为宽960 * 高640 // box2d世界为宽10米 * 6.67米 (因为10米是比较理想的模拟情况) // 因此 像素转成米 的比例是 96 // 如果,要把 像素转成米 只要 像素/RATIO // 如果,要把 米转成像素 只要 米*RATIO (把物理世界中的刚体 在界面上更新坐标时) #define RATIO 960.0/10.0f USING_NS_CC; Scene* Box2DScene::createScene() { // 'scene' 自动释放 // 创建一个scene auto scene = Scene::create(); // 'layer' 自动释放 auto layer = Box2DScene::create(); // 将图层 添加到场景中 scene->addChild(layer); // 返回 填充好图层的 场景 return scene; } // 在 "init" 方法中,实例化自己要用的精灵对象 bool Box2DScene::init() { // 1. 调用父类的init , cpp 没有super,直接写父类名 if ( !Layer::init() ) return false; // 屏幕尺寸 winSize = Director::getInstance()->getVisibleSize(); // 2、创建一个物理世界,参数 是x y 方向的重力加速度,负数表示 重力向下 world = new b2World(b2Vec2(0,-9.8)); // 设置碰撞检测 的侦听者 为当前Layer world->SetContactListener(this); // 3、开启时钟方法,在时钟方法中,让世界 向前运行 scheduleUpdate(); // 4、创建并添加一个运行的物体 RectBody // 参数 x 5 y 3,x和y是世界坐标中的位置,类型是 b2_dynamicBody addRectBody(5,3,b2_dynamicBody); // 5、添加一个地板 addGroundBody(); // 6、创建一个漂浮的物体 addRectBody(1,5,b2_kinematicBody); return true; } #pragma mark - 添加一个刚体 // 添加一个静止的或运动的Rect刚体,通过参数type指定,x和y是世界坐标中的位置 void Box2DScene::addRectBody(float x, float y, b2BodyType body_type) { // 1.1 结构体b2BodyDef // 每个刚体都有自身的 固有的 必须的 b2BodyDef属性 b2BodyDef def; // 在世界坐标中 的位置:第x米,第y米处 def.position = b2Vec2(x, y); // 设置【b2BodyDef】的 类型 (运动的或静止的或漂浮的) def.type = body_type; // 设置【b2BodyDef】的 线速度 y = 10 ,表示物体向上飞 if(body_type == b2_dynamicBody){ // 动态物体 自由落体 def.linearVelocity = b2Vec2(0, 9.8); }else{ // 漂浮物体 向右飘动 def.linearVelocity = b2Vec2(1, 0); } // 设置【b2BodyDef】的 子弹效应 (防止碰撞检测时 由于速度 太快,而失效;如本应反弹,结果陷入地板内) // def.bullet = true; // 1.2 通过调用world的方法,创建一个Body物体 // 参数 是一个 b2BodyDef,它是构造一个刚体必须的、固有的东东 // 因为,每个刚体都有自身的 b2BodyDef属性 b2Body* body = world->CreateBody(&def); // ************************************************* // 2.1 形状分为 圆和多边形 b2PolygonShape shape; shape.SetAsBox(0.5, 0.5); // 2.2 一个刚体 有多个 b2FixtureDef // 一个 b2FixtureDef 是依附在刚体 身上的物理物质的属性 // 每一个 b2FixtureDef 又有形状shape、密度、摩擦系数等成员属性 b2FixtureDef fixtureDef; // 每一个 b2FixtureDef都有一个成员shape fixtureDef.shape = &shape; // 密度 fixtureDef.density = 1; // 摩擦系数 fixtureDef.friction = 0.3; // 为刚体 添加一个 b2FixtureDef body->CreateFixture(&fixtureDef); // ************************************************* // 3、创建并添加一个 cocos2d 的精灵 auto s = Sprite::create(); // 0.5是物理世界中的精灵大小 单位是 米 // 即在物理世界中,精灵 是一个1米 * 1米的方块 s->setTextureRect(Rect(0, 0, 0.5*2*RATIO, 0.5*2*RATIO)); // 添加到图层Layer addChild(s); // ************************************************* // 4、绑定 cocos2d界面上的精灵 body->SetUserData(s); } #pragma mark - 添加一个地板 void Box2DScene::addGroundBody() { // 1.1 结构体b2BodyDef // 每个刚体都有自身的 固有的 必须的 b2BodyDef属性 b2BodyDef def; // 在世界坐标中 的位置:第x米,第y米处 这个是在 log("宽:%f",winSize.width); // 位置 def.position = b2Vec2(480/RATIO,0); // 设置【b2BodyDef】的 类型 (运动的或静止的或漂浮的) def.type = b2_staticBody; // 1.2 通过调用world的方法,创建一个Body物体 // 参数 是一个 b2BodyDef,它是构造一个刚体必须的、固有的东东 // 因为,每个刚体都有自身的 b2BodyDef属性 groundBody = world->CreateBody(&def); // ************************************************* // 2.1 形状分为 圆和多边 b2PolygonShape groundShape; // 尺寸: 在物理世界中的 半长和 半宽 多少米 groundShape.SetAsBox(480/RATIO, 0.5); // 2.2 一个刚体 有多个 b2FixtureDef // 一个 b2FixtureDef 是依附在刚体 身上的物理物质的属性 // 每一个 b2FixtureDef 又有形状shape、密度、摩擦系数等成员属性 b2FixtureDef fixureDef; // 形状 fixureDef.shape = &groundShape; // 密度 fixureDef.density = 1; // 摩擦系数 fixureDef.friction = 0.3; groundBody->CreateFixture(&fixureDef); } #pragma mark - 时钟方法 void Box2DScene::update(float dt) { // 1、让物理世界 的时间和位置向前迭代 // 参数:时间差,速度迭代,位置迭代;官方推荐 8和3 world->Step(dt,8,3); // 2、取出世界中的所有刚体,改变其位置 Sprite *s; // 链表 for (b2Body *b = world->GetBodyList(); b; b=b->GetNext()) { // log("y:%f米",b->GetPosition().y); if (b->GetUserData()) { // 刚体绑定的 精灵 s = (Sprite*)b->GetUserData(); // 更新精灵 在cocos2d中的位置 ; 单位要从米转成像素 只需 米*RATIO 即可 s->setPosition(b->GetPosition().x*RATIO, b->GetPosition().y*RATIO); } } } #pragma mark - 碰撞检测 // 接口中的方法,是一个固定定法 void Box2DScene::BeginContact(b2Contact *contact){ // 碰撞有一方 是地板,则说明 检测到了碰撞 b2Fixture *A = contact->GetFixtureA(); b2Body *aBody = A->GetBody(); b2Fixture *B = contact->GetFixtureB(); b2Body *bBody = B->GetBody(); if (aBody == groundBody||bBody == groundBody) { log("有物体落在了地板上"); } }