cocos2dx box2d使用(一)

本例子使用的是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 已被调谐使用米,千克和秒来作单位,所以你可以用米来考虑长度。然而, 改变单位系统是可能的。 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值