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 测试 layer , box2d 世界是独立于 cocos 的 scene 的
     *
     *@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 已被调谐使用米,千克和秒来作单位,所以你可以用米来考虑长度。然而, 改变单位系统是可能的。 

转载于:https://www.cnblogs.com/chiefCTO/p/3735526.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值