cocos2d-x Box2d 入门例子

1.效果图(动态的gif见底部):

 

 

还记得这篇文章吗?cocos2d-x
Touch 事件应用的一个例子 
球跟球之间的碰撞,球跟壁的碰撞使用了简单的向量。球最终停止下来也是因为向量不断地变小。这次我们要改用物理引擎Box2d来让球碰撞!先下载这个项目,打开Release.win32/Air Hockey.win32.exe先来个试玩吧。

 

2.Box2d如何在cocos2d-x中使用简单介绍

 

Box2d引擎中核心的是一个叫b2World的东西,它会创建一些b2Body的物体,当然这些物体的形状有多边形,圆形等,属性也各异:比如密度有大有小。创建完后,在游戏的一直调用的update函数里加上b2World->Step(),那些b2Body的物体就会根据你设置的属性有物理反应了,但是他们没有纹理,但他们有position,rotation等属性,我们把这属性应用到我们Cocos2d-x中的Sprite属性时,Sprite就像真的物体一样动起来了。

 

2.1 b2World设置

 

Box2d中使用的是一个叫做b2Vec2的向量。

?


1

2

3

4

5

6

7

8

9

10

11

b2World
*_world;
//定义一个b2World指针变量,它将设置一些属性,然后一些

                                           //物体比如圆形的方形的都将由它创建

b2Vec2
gravity;

    gravity.Set(0.0f,
0.0f);
//我们是在一个平面上,所以只需要将重力加速度设置为0

    _world
=
new

b2World(gravity);

 

    _world->SetAllowSleeping(true);

    _world->SetContinuousPhysics(true);

    _collisionListener
=
new

CollisionListener();
//b2ContactListener,这里可以自定义处理物体碰撞发生的事情

                                                 //比如球碰到球门,我们希望重置游戏。

    _world->SetContactListener(_collisionListener);

 

2.2 b2Body的创建

 

我们主要有3种类型的b2Body, dynamic, static, 和 kinematic,根据名字就知道他们的用途。

b2Body创建需要一个叫b2BodyDef的结构体作为参数,b2BodyDef有一些属性比如type, position,velocity,angle,等。

b2Body还需要创建Fixture,需要一个b2FixtureDef的结构体,它也有一些属性跟这物体相关的,比如:长宽高,半径,还有density,elasticity,friction等属性。下面是一个创建球的例子。

?


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

b2BodyDef
bodyDef;

bodyDef.type
= b2_dynamicBody;
//设置类型

b2Body
*body = world->CreateBody(&bodyDef);

 

b2CircleShape
circle;
//创建一个圆形

circle.m_radius
= 20.0 / PTM_RATIO;
//设置半径

 

//定义fixture

b2FixtureDef
fixtureDef;

fixtureDef.shape
= &circle;

fixtureDef.density
= 1;

fixtureDef.restitution
= 0.7;

fixtureDef.friction
= 0.4;
//摩擦力

 

body->CreateFixture(&fixtureDef);

读者可以查看我们项目中Ball.cpp中的initBall,Goal.cpp中的initGoal,细细体会。

3. b2Sprite 类

 

我们建立了一个b2Sprite类它继承了CCSprite,有一个b2Body的属性,所以它拥有CCSprite和b2Body两个类的属性的相加。这不是普通的CCSprite,因为它有b2Body的属性,想象下,CCSprite是负责处理一个精灵的外表,而它的内心,比如位置等方面是由物理引擎来改变的。

?


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

class

b2Sprite :
public

CCSprite{

public:

    b2Sprite(GameLayer
*game,
int

type);

 

    CC_SYNTHESIZE(b2Body*,
_body, Body);

    CC_SYNTHESIZE(GameLayer*,
_game, Game);

    CC_SYNTHESIZE(int,
_type, Type);

 

    virtual

void

setSpritePosition(CCPoint position);

    virtual

void

update(
float

dt);

    virtual

void

hide(
void);

    virtual

void

reset(
void);

    virtual

float

mag();

};

//两个核心方法

//当你为一个精灵设置位置和旋转角度的时候,会同样改变它的b2Body的位置和旋转角度

void

b2Sprite::setSpritePosition(CCPoint position){

    setPosition(position);

 

    if(_body){

        _body->SetTransform(b2Vec2(

            position.x
/ PTM_RATIO,

            position.y
/ PTM_RATIO),

            _body->GetAngle());

    }

}

 

//当精灵的b2Body根据碰撞发生位置上的偏移时,会改变它的精灵的位置和旋转角度

void

b2Sprite::update(
float

dt){

 

    if(_body
&& isVisible()){

        setPositionX(_body->GetPosition().x
* PTM_RATIO);

        setPositionY(_body->GetPosition().y
* PTM_RATIO);

        setRotation(CC_RADIANS_TO_DEGREES(-1
* _body->GetAngle()));

    }

}

 

4. 游戏介绍

 

总算把理论知识讲的差不多了,来看看我们游戏是如何应用Box2d的。

 

 

 

  1. 玩家用手指头触摸移动的白球我们建了一个Player的类,因为它是主动的,所以它的位置由触摸点决定,但会影响b2Body位置。
  2. 红球,我们建立一个Ball的类,因为它是被动的,所以它的位置由b2Body决定
  3. 红色的6根线段是b2Body,它的Fixture的形状是 b2EdgeShape,边的意思,球会跟它碰撞
  4. 我们还建立了两个球门,就是图中两端黑色矩形,因为与它相碰时,我们不需要改变球的b2Body属性,但需要处理事件,所以isSensor设置为ture

理解上面提到的4点,我们的游戏就那么回事了。你可以跟没有使用Box2d的进行比较。

 

5.项目源码下载(请用7z解压)

 http://www.waitingfy.com/?attachment_id=700

 

http://www.waitingfy.com/?p=696

6.游戏动态图

 

参考:

《Cocos2d-X by Example Beginner’s Guide》

时间: 2024-11-02 09:43:17

cocos2d-x Box2d 入门例子的相关文章

Mybatis入门例子

Mybatis是轻量级的持久化框架,的确上手非常快. Mybatis大体上的思路就是由一个总的config文件配置全局的信息,比如mysql连接信息等.然后再mapper中指定查询的sql,以及参数和返回值. 在Service中直接调用这个mapper即可. 依赖的jar包 <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <versio

一个经典的ADO.NET入门例子

ado 众所周知,ADO.NET相对于ADO的最大优势在于对于数据的更新修改可以在与数据源完全断开联系的情况下进行,然后再把数据更新情况传回到 数据源.这样大大减少了连接过多对于数据库服务器资源的占用.下面是我在<ADO.NET实用指南>这本书上看到的一个例子,比较清楚的讲解 了ADO.NET的使用方法.Imports System.Data.SqlClientImports System.DataImports System.Data.Common Public Class Form1 In

一个经典的ADO.NET入门例子_ASP.NET

众所周知,ADO.NET相对于ADO的最大优势在于对于数据的更新修改可以在与数据源完全断开联系的情况下进行,然后再把数据更新情况传回到  数据源.这样大大减少了连接过多对于数据库服务器资源的占用.下面是我在<ADO.NET实用指南>这本书上看到的一个例子,比较清楚的讲解  了ADO.NET的使用方法.  Imports System.Data.SqlClient  Imports System.Data  Imports System.Data.Common  Public Class For

26.3. 入门例子

26.3.1. 订阅例子 package cn.netkiller.kafka.test; import java.util.Arrays; import java.util.Properties; import org.apache.kafka.clients.consumer.ConsumerRecord; import org.apache.kafka.clients.consumer.ConsumerRecords; import org.apache.kafka.clients.con

Spring+Struts+Hibernate入门例子Wiring Step By Step

wiring下载点http://www.onjava.com/onjava/2004/04/07/examples/wiring.zip 说重点吧,主要是注意几点! 一 前期工作1. 下载Xdoclet,DB2Java和Proxool,并把Proxool lib目录下的.jar拷到wiring WEB-INF下的lib目录. 把相应的Spring,Hibernate,Struts要用到的包也拷进lib目录,如aopalliance.jar;                   cglib-ful

Delphi类的入门例子(9): 获取对象的 RTTI 属性与事件的函数

unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, xmldom, XMLIntf, XMLBrokr, msxmldom, XMLDoc; type TForm1 = class(TForm) Button1: TButton; Button2: TButton; Memo1: TMemo; Memo2:

Delphi类的入门例子(8): 遍历窗体中所有控件的函数

//显示窗体中所有控件的函数 function GetCtrls(Control: TWinControl; List: TStringList): Boolean; var i: Integer; obj: TWinControl; begin for i := 0 to Control.ControlCount-1 do begin obj := TWinControl(Control.Controls[i]); List.Add(obj.Name); //如果控件中包含其他控件, 则递归调

Delphi类的入门例子(7): 遍历窗体的所有父类

unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TForm1 = class(TForm) Button1: TButton; Button2: TButton; Button3: TButton; Button4: TButton; procedure Button1Click(Sender:

Delphi类的入门例子(4): property

//类单元unit Person; interface type TPerson = class(TObject) private FName: string; FAge: Integer; public procedure SetName(const strName: string); procedure SetAge(const intAge: Integer); property Name: string read FName write SetName; property Age: In