cocos2d-x学习笔记(20)-- box2d入门(转)
来源:互联网 发布:有淘宝账号怎么开店 编辑:程序博客网 时间:2024/06/05 10:53
转自:http://www.2cto.com/kf/201209/154683.html
cocos2d-x学习笔记(20)-- box2d入门
在看本次的文章前,最好先看我写的box2d物理引擎自学笔记整理1做做一些准备工作,以便更好地理解代码。
step1:创建coco2d-win32工程,注意在创建时记得勾上Box2D选项,命名为box2d;
step2:在HelloWorldScene.h中添加如下类:
[plain]
class Box2DTest:public CCLayer
{
protected:
b2World* m_world;
public:
Box2DTest();
~Box2DTest();
void addSprite(CCPoint point);
void update(ccTime dt);
};
step3:在HelloWorldScene.cpp中添加下面的代码:
const int tagSprite = 1;
#define PTM_RATIO 32
[plain]
/************************************************************************/
/* Box2DTest */
/************************************************************************/
Box2DTest::Box2DTest()
{
setIsTouchEnabled(true);
setIsAccelerometerEnabled(true);//设置加速
CCSize size = CCDirector::sharedDirector()->getWinSize();
b2Vec2 gravity(0.0f, -10.0f);
bool doSleep = true;
m_world = new b2World(gravity);
m_world->SetAllowSleeping(doSleep);
m_world->SetContinuousPhysics(true);
//定义地表物体
b2BodyDef groundBodyDef;
b2Body* groundBody = m_world->CreateBody(&groundBodyDef);
b2PolygonShape groundBox;
//墙底
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);
CCSpriteBatchNode* brick = CCSpriteBatchNode::batchNodeWithFile("brick.png");
addChild(brick, 2, tagSprite);
addSprite(ccp(size.width / 2, size.height / 2));
scheduleUpdate();
}
[plain]
Box2DTest::~Box2DTest()
{
delete m_world;
m_world = NULL;
}
首先是创建世界对象并设置重力场。
接着是想世界对象添加地表物体,这里地表物体是一个空心的四边形,相当于四幅墙壁,由于地表物体是静态物体,故groundBody->CreateFixture()第二个参数密度设置为0;
在构造函数里调用scheduleUpdate()函数用于模拟时间更新,并在update中实现更新。
在box2d中,通过不停调用step来更新画面。
[plain]
void Box2DTest::addSprite(CCPoint point)
{
CCSpriteBatchNode* batch = (CCSpriteBatchNode*)getChildByTag(tagSprite);
CCSprite *sprite = CCSprite::spriteWithTexture(batch->getTexture(), CCRectMake(0,0,32,32));
batch->addChild(sprite);
sprite->setPosition(ccp(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);
}
在这里要说说box2d中的单位,由于box2d中使用的是米作为长度单位。但在编程中,我们使用的图片都是使用像素作为基本单位。
为此,我总结了一个原则:凡是要向世界对象中添加物体的,都需要将像素单位转化为米单位。凡是要将世界对象中的物体显示在屏幕上时,要将物体的米单位转化为像素单位。
[plain]
b2BodyDef bodyDef;
bodyDef.type = b2_dynamicBody;
bodyDef.position.Set(point.x / PTM_RATIO, point.y/ PTM_RATIO);
bodyDef.userData = sprite;
[plain] view plaincopy
//将sprite精灵和物体对象绑定
[plain]
b2Body * body = m_world->CreateBody(&bodyDef);
这里由于我们需要向世界对象中添加一个动态物体,则按照我说的原则凡是入世界对象的就需要转为为米单位,这里我是使用了32像素为1米(见PTM_RATIO定义)。
[plain]
b2PolygonShape dynamicBox;
dynamicBox.SetAsBox(0.5f, 0.5f);
还有这里,由于SetAsBox设置的是实际距离的一般,那么实际的长度和宽度是1米和1米,即相当于32像素长和32像素宽,正好是我使用的图片大小。
[plain]
for(b2Body* b = m_world->GetBodyList(); b; b = b->GetNext())
{
if(b->GetUserData() != NULL)
{
CCSprite* sprite = (CCSprite*)b->GetUserData();
sprite->setPosition(ccp(b->GetPosition().x * PTM_RATIO, b->GetPosition().y * PTM_RATIO));
}
}
这段代码首先是便利世界对象中的所有物体对象,然后将物体对象显示在屏幕上。注意,由于这里我们是将世界对象中的物体显示在屏幕中,故需要将米单位转为为像素单位。
[plain]
void Box2DTest::update(ccTime 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)
{
CCSprite* sprite = (CCSprite*)b->GetUserData();
sprite->setPosition(ccp(b->GetPosition().x * PTM_RATIO, b->GetPosition().y * PTM_RATIO));
}
}
}
这里update是每帧更新的内容,程序会自动调用。step函数的第一个参数是时间步,也叫做积分器,官方文档的解释如下:
Box2D使用了一个叫积分器(integrator)的数值算法。 积分器在离散的时间点上模拟连续的物理方程。 它与传统的游戏动画循环一同运行。我们需要为Box2D选取一个时间步。通常来说用于游戏的物理引擎需要至少 60Hz 的速度,也就是 1/60 的时间步。你可以使用更大的时间步,但是你必须更加小心地为你的世界调整定义。我们也不喜欢时间步变化得太大,所以不要把时间步关联到帧频(除非你真的必须这样做)。
第二个参数是速度迭代,可以调整物体的运动。第三个参数是位置迭代,可以调整物体的位置,减少物体间的重叠。
step5:
这里,只有一个物体显得比较单调。为此,我修改了一下原来的代码,通过点击屏幕不断想世界对象增加物体。
[cpp]
void Box2DTest1::ccTouchesEnded(CCSet *pTouches, CCEvent *pEvent)
{
CCSetIterator it;
CCTouch* touch;
for(it = pTouches->begin(); it != pTouches->end(); it++)
{
touch = (CCTouch*)(*it);
CCPoint location = touch->locationInView(touch->view());
location = CCDirector::sharedDirector()->convertToGL(location);
addSprite(location);
}
}
在Box2DTest1中添加ccTouchesEnded类,以响应触屏事件。
同时修改update函数:
[cpp]
void Box2DTest1::update(ccTime 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)
{
CCSprite* sprite = (CCSprite*)b->GetUserData();
sprite->setPosition(ccp(b->GetPosition().x * PTM_RATIO, b->GetPosition().y * PTM_RATIO));
sprite->setRotation( -1 * CC_RADIANS_TO_DEGREES(b->GetAngle()) );
}
}
}
修改为 CCSprite *sprite = CCSprite::spriteWithTexture(batch->getTexture(), CCRectMake((rand()%2) * 32,(rand()%2) * 32,32,32));
- cocos2d-x学习笔记(20)-- box2d入门
- cocos2d-x学习笔记(20)-- box2d入门
- cocos2d-x学习笔记(20)-- box2d入门(转)
- cocos2d-x box2d 入门
- cocos2d-x Box2d 入门例子
- cocos2d-x Box2d 入门例子
- cocos2d-x初探学习笔记--物理引擎box2d(2)
- cocos2d-x初探学习笔记--物理引擎box2d(1)
- cocos2d-x初探学习笔记(20)--物理引擎box2d(2)
- cocos2d-x初探学习笔记(20)--物理引擎box2d(2)
- cocos2d-x 自学笔记之box2D
- cocos2d-x 物理引擎BOX2d学习
- cocos2d-x mruby学习笔记--入门
- cocos2d-x初探学习笔记(19)--物理引擎box2d(1)
- cocos2d-x学习笔记-box2d实现物理引擎新旧版本的不同
- Box2d学习笔记一:在cocos2d-x中启动调试绘图
- cocos2d-x初探学习笔记(19)--物理引擎box2d(1)
- Cocos2d-x学习笔记(十二)—— Box2d物理引擎(未完)
- VC/MFC列表CListCtrl类的LVCOLUMN和LVITEM详解
- 13--1递归求奇数连乘的积
- 新晨-交换平台系统
- 学好Python必读的几篇文章
- 新APP《故事会中篇故事集》成功上架 & 新应用《故事中国》安卓版预告
- cocos2d-x学习笔记(20)-- box2d入门(转)
- 2013年11.25本周计划
- 静态方法为什么只能使用静态变量
- http 协议
- ZOJ 2476 Total Amount A的好辛苦
- Linux用户空间与内核空间
- Ubuntu 下安装 Code::Blocks
- C/C++语言变量声明内存分配
- 进入工作室考核有感