• cocos2dx box2d使用(一)


    出处:https://www.evernote.com/shard/s262/sh/bf561bda-0458-4502-835b-903846f81d68/68e6634bddec74c5a2d5f8dd839eba0a

    本例子使用的是cocos2d-x 3.0版本

    1. 首先创建一个cocos2d的c++工程,这里就不多做说明了!本例子的项目名称是MyGame
    2. 其次,在MyGame的工程设置里Build Settings下,把CC_ENABLE_CHIPMUNK_INTEGRATION=1改为CC_ENABLE_BOX2D_INTEGRATION=1,同样把项目所引入的cocos2d的工程里改一下,但cocos2d的工程修改的地方有点特别!screenshot.png如上图的工程,非target!
    3. 到此,box2d的环境已经设定好了!
    现在工程已经创建完成了,环境也设定好了,下代码工程:
    screenshot.png
    创建一个layer,用于放置所有的box2d对像和项目的精灵
    其中的头文件如下:
    //
    //  Box2dTest.h
    //  MyGame
    //
    //  Created by Poche on 5/17/14.
    //
    //

    #ifndef __MyGame__Box2dTest__
    #define __MyGame__Box2dTest__

    #include "cocos2d.h"
    #include
     "Box2D/Box2D.h"

    class Box2dTest : public cocos2d::Layer {
    public:
        Box2dTest();
       
     virtual ~Box2dTest();
       
     CREATE_FUNC(Box2dTest);
       
       
     /**
         *@brief
    初始化box2d测试layerbox2d世界是独立于cocosscene
         *
         *@Modified by poche at 2014-05-18 18:00:17
         *
         *@return
    是否初始化成功
        **/

       
     bool init();
       
     /**
         *@brief
    初始化box2d世界
         *
         *@Modified by poche at 2014-05-18 18:01:43
        **/

       
     void initWorld();
    private:
       
     b2World *m_world;   /// box2d世界
       
     /// layer上的点击加调
       
     CC_SYNTHESIZE_RETAIN(cocos2d::EventListenerTouchAllAtOnce*, m_touchListener,_touchListener);
    public:
       
     /**
         *@brief
    添加精灵到指定坐标
         *
         *@Modified by poche at 2014-05-18 18:02:44
         *@param point
     坐标
        **/

       
     void AddSprite(cocos2d::Point point);
       
     /**
         *@brief
    每帧检查box2d物体并且更新cocos的精灵的状态(位置等)
         *
         *@Modified by poche at 2014-05-18 18:03:25
         *@param dt
     时间间隔
        **/

       
     void update(float dt);
       
     /**
         *@brief
    添加点击回调事件
         *
         *@Modified by poche at 2014-05-18 18:04:39
        **/

       
     void addLayerTouchListener();
       
     /**
         *@brief
    点击结束后的加调方法
         *
         *@Modified by poche at 2014-05-18 18:04:56
         *@param touches
     点击集合
         *@param event
     事件类型
        **/

       
     void touchesEnd(const std::vector<cocos2d::Touch*> touches, cocos2d::Event *event);
       
     virtual void onExit();
    };

    #endif /* defined(__MyGame__Box2dTest__) */
     
    下面看一下.cpp的代码:
    //
    //  Box2dTest.cpp
    //  MyGame
    //
    //  Created by Poche on 5/17/14.
    //
    //

    #include "Box2dTest.h"
    USING_NS_CC
    ;

    /// box2d里,其用到的单位是现实中的单位,米等
    /// 所以在游戏里,我们需要作出转换
    /// cocos2d里,每32个像素就相当box2d里的一米
    #define PTM_RATIO 32

    const int tagSprite = 1;

    Box2dTest::Box2dTest()
    :
     m_touchListener(NULL)
    {
       
    }

    Box2dTest::~Box2dTest() {
       
     CC_SAFE_RELEASE(m_touchListener);
       
     /// 记得移除对像,要不然会泄露
       
     delete m_world;
       
     m_world = NULL;
    }

    bool Box2dTest::init() {
       
     /// 添加点击响应
       
     addLayerTouchListener();
       
     /// 初始化世界
       
     initWorld();
       
     return true;
    }
    void Box2dTest::initWorld() {
       
       
     auto size = Director::getInstance()->getWinSize();
       
     /// 设置box2d世界重力方向
       
     b2Vec2 gravity(0.0f, -10.0f);
       
     bool doSleep    = true;
       
       
     /// 生成box2d世界
       
     m_world = new b2World(gravity);
       
     /// 是否允许睡眠
       
     m_world->SetAllowSleeping(doSleep);
       
     m_world->SetContinuousPhysics(true);
       
       
     /// 地表物体定义
       
     b2BodyDef groundBodyDef;
       
     /// 通过地表物体定义生成地表物体
       
     b2Body* groundBody  = m_world->CreateBody(&groundBodyDef);
       
     /// 形状
       
     b2PolygonShape groundBox;
       
       
     /// 作为box形态布局
       
     /// 第一个参数  物体的宽
       
     /// 第二个参数  物体的高
       
     /// 第三个参数  物体的位置
       
     /// 第四个参数  物体中角度
       
     /// 墙底
        groundBox.
    SetAsBox(size.width / PTM_RATIO, 0, b2Vec2(0, 0), 0);
       
     /// 把已经生成的物体放入世界中
       
     /// 第一个参数  要放入的物体
       
     /// 第二个参数  物体的质量
        groundBody->
    CreateFixture(&groundBox, 0);
       
     /// 墙顶
        groundBox.
    SetAsBox(size.width / PTM_RATIO, 0, b2Vec2(0, size.height / PTM_RATIO), 0);
        groundBody->
    CreateFixture(&groundBox, 0);
       
     /// 左墙
        groundBox.
    SetAsBox(0, size.height / PTM_RATIO, b2Vec2(0, 0), 0);
        groundBody->
    CreateFixture(&groundBox, 0);
       
     /// 左墙
        groundBox.
    SetAsBox(0, size.height / PTM_RATIO, b2Vec2(size.width / PTM_RATIO, 0), 0);
        groundBody->
    CreateFixture(&groundBox, 0);
       
       
     /// cocos2d里的精灵
       
     auto brick  = SpriteBatchNode::create("CloseNormal.png");
       
     addChild(brick, 2, tagSprite);
       
       
     /// 每帧对cocos2d的精灵更新
       
     schedule(schedule_selector(Box2dTest::update));
    }

    void Box2dTest::AddSprite(cocos2d::Point point) {
       
     auto batch = (SpriteBatchNode*)getChildByTag(tagSprite);
       
       
     auto sprite = Sprite::createWithTexture(batch->getTexture(), Rect(0,0,32,32));
        batch->
    addChild(sprite);
       
        sprite->
    setPosition(Point(point.x, point.y));
       
       
     /// 创建动态物体
       
     /// 物体定义
       
     b2BodyDef bodyDef;
       
     /// 物体为动态物体
        bodyDef.
    type = b2_dynamicBody;
       
     /// 物体的位置
        bodyDef.
    position.Set(point.x / PTM_RATIO, point.y/ PTM_RATIO);
       
     /// 将已经生成的精灵捆绑到物体上
        bodyDef.
    userData = sprite;
       
     /// 创建物体
       
     b2Body * body = m_world->CreateBody(&bodyDef);
       
       
     b2PolygonShape dynamicBox;
        dynamicBox.
    SetAsBox(0.5f, 0.5f);
       
       
     b2FixtureDef fixtureDef;
        fixtureDef.
    shape = &dynamicBox;
       
     /// 设置摩擦系数
        fixtureDef.
    friction = 0.3f;
       
     /// 设置密度
        fixtureDef.
    density = 1.0;
        body->
    CreateFixture(&fixtureDef);
    }

    void Box2dTest::update(float dt) {
       
     int velocityIterations = 8;
       
     int positionIterations = 1;
       
       
     //每次游戏循环你都应该调用b2World::Step
       
     m_world->Step(dt, velocityIterations, positionIterations);
       
       
       
     for(b2Body* b = m_world->GetBodyList(); b; b = b->GetNext())
        {
           
     if(b->GetUserData() != NULL)
            {
               
     /// 更新cocos2d对像
               
     auto sprite = (Sprite*)b->GetUserData();
                sprite->
    setPosition(Point(b->GetPosition().x * PTM_RATIO, b->GetPosition().y * PTM_RATIO));
                sprite->
    setRotation( -1 * CC_RADIANS_TO_DEGREES(b->GetAngle()) );
            }
        }
    }

    void Box2dTest::addLayerTouchListener() {
       
     set_touchListener(EventListenerTouchAllAtOnce::create());
       
     get_touchListener()->onTouchesEnded = CC_CALLBACK_2(Box2dTest::touchesEnd, this);
       
     _eventDispatcher->addEventListenerWithSceneGraphPriority(get_touchListener(), this);
       
    }

    void Box2dTest::onExit() {
       
     Layer::onExit();
       
     unschedule(schedule_selector(Box2dTest::update));
       
     _eventDispatcher->removeEventListener(get_touchListener());
    }

    void Box2dTest::touchesEnd(const std::vector<cocos2d::Touch *> touches, cocos2d::Event *event) {

       
     for (auto& touch : touches)
        {
           
     auto location = touch->getLocationInView();
            location =
     Director::getInstance()->convertToGL(location);
           
           
     AddSprite(location);
        }
    }
     
    解释:
    在这里要说说box2d中的单位,由于box2d中使用的是米作为长度单位。但在编程中,我们使用的图片都是使用像素作为基本单位。
    凡是要向世界对象中添加物体的,都需要将像素单位转化为米单位。凡是要将世界对象中的物体显示在屏幕上时,要将物体的米单位转化为像素单位,在cocos2d里,大多用到的32个像素为一米,能否改就不得而知了!

    SetAsBox 函数接收了半个宽度和半个高度,这样的话,地面盒就是 100 个单位宽(x 轴)以及 20 个单位高(y 轴)。Box2D 已被调谐使用米,千克和秒来作单位,所以你可以用米来考虑长度。然而, 改变单位系统是可能的。 

  • 相关阅读:
    .NET Core 使用NPOI读取Excel返回泛型List集合
    C# 判别系统版本以及Win10的识别办法
    WPF 程序员休息数字时钟
    分享一个淘宝/天猫/京东/阿里 图片抓取工具
    记一次数据库同步经历(sql server 2008)
    datagridview 如何显示记载中
    关于如何解决bootstrap table 列 切换 刷新 高度不一样
    js 中 函数的返回值问题
    winform 实现定位
    winform 里 如何实现文件上传
  • 原文地址:https://www.cnblogs.com/conerlius/p/3735526.html
Copyright © 2020-2023  润新知