box2d 让物体突然静止怎样让砖块并列

下次自动登录
现在的位置:
& 综合 & 正文
cocos2dx视频教程进阶篇–第2天–打砖块游戏-box2d物理引擎–续
注意:这是第二篇,上回
我们接着写
感觉直接看代码太枯燥的,请关注视频讲解
更新:高清avi视频和源代码已经提供下载:
百度网盘: 里面的进阶篇。
2.主场景头文件
#ifndef __HELLOWORLD_SCENE_H__
#define __HELLOWORLD_SCENE_H__
#include "cocos2d.h"
#include "../../../../external/Box2D/Box2D.h"
#include "MyContactListener.h"
USING_NS_CC;
class HelloWorld : public cocos2d::CCLayer
b2World* _
b2Body* _groundB
CCSprite* _ballS
CCSprite* _paddleS
b2MouseJoint* _mouseJ
MyContactListener*
b2Fixture* _
// Here's a difference. Method 'init' in cocos2d-x returns bool, instead of returning 'id' in cocos2d-iphone
virtual bool init();
// there's no 'id' in cpp, so we recommend returning the class instance pointer
static cocos2d::CCScene* scene();
// a selector callback
void menuCloseCallback(CCObject* pSender);
// implement the "static node()" method manually
CREATE_FUNC(HelloWorld);
void update(float delta);
bool ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent);
void ccTouchMoved(CCTouch *pTouch, CCEvent *pEvent);
void ccTouchEnded(CCTouch *pTouch, CCEvent *pEvent);
#endif // __HELLOWORLD_SCENE_H__
3. 结束场景
#include "GameOverScense.h"
bool GameOverScene::initWithWin( bool isWin )
if (!CCLayer::init()){
char words[64];
if (isWin){
sprintf(words, "Man you rock!");
sprintf(words, "Man you suck!");
CCLabelTTF* label = CCLabelTTF::create(words, "Arial", 30);
label-&setPosition(ccp(320, 300));
this-&addChild(label);
CCScene* GameOverScene::scenseWithWin( bool isWin )
CCScene* sc = CCScene::create();
GameOverScene* layer = new GameOverScene();
layer-&initWithWin(isWin);
sc-&addChild(layer);
4. 结束场景头文件
#include "cocos2d.h"
USING_NS_CC;
class GameOverScene : public CCLayer
bool initWithWin(bool isWin);
static CCScene* scenseWithWin(bool isWin);
5. 碰撞监听文件
#include "MyContactListener.h"
void MyContactListener::BeginContact( b2Contact* contact )
MyContactPeer peer = {contact-&GetFixtureA(), contact-&GetFixtureB()};
_contacts.push_back(peer);
void MyContactListener::EndContact( b2Contact* contact )
MyContactPeer peer = {contact-&GetFixtureA(), contact-&GetFixtureB()};
vector&MyContactPeer&::iterator pos, posF
for (pos = _contacts.begin(); pos != _contacts.end(); pos ++){
MyContactPeer onePeer = *
if (onePeer.fixA == peer.fixA && onePeer.fixB == peer.fixB){
posFound =
_contacts.erase(posFound);
MyContactListener::MyContactListener():_contacts()
MyContactListener::~MyContactListener()
void MyContactListener::PreSolve(b2Contact* contact, const b2Manifold* oldManifold)
void MyContactListener::PostSolve(b2Contact* contact, const b2ContactImpulse* impulse)
6.碰撞监听头文件
#include "../../../../external/Box2D/Box2D.h"
#include &vector&
struct MyContactPeer{
b2Fixture* fixA;
b2Fixture* fixB;
class MyContactListener : public b2ContactListener{
vector&MyContactPeer& _
MyContactListener();
~MyContactListener();
void BeginContact(b2Contact* contact) ;
void EndContact(b2Contact* contact);
void PreSolve(b2Contact* contact, const b2Manifold* oldManifold);
void PostSolve(b2Contact* contact, const b2ContactImpulse* impulse);
7 box2d 帮助类
once //避免重复包含
#include "../../../../external/Box2D/Box2D.h"
class Box2dUtils{
static b2Body* createDynamicBody(float posX, float posY, void* userData, b2World* _world){
b2BodyDef ballBodyD
ballBodyDef.type = b2_dynamicB //
ballBodyDef.position.Set(posX, posY);
ballBodyDef.userData = userD // 把屏幕中的精灵作为 物理世界中物体的 userData
b2Body* ball = _world -&CreateBody(&ballBodyDef);
static b2Fixture* createFixture(b2Shape* shape, float density, float friction, float restitution, b2Body* ball ){
b2FixtureDef ballFixD
ballFixDef.shape =
ballFixDef.density =
ballFixDef.friction =
ballFixDef.restitution =
return ball-&CreateFixture(&ballFixDef);
转载注明出处:
【上篇】【下篇】他的最新文章
他的热门文章
您举报文章:
举报原因:
原文地址:
原因补充:
(最多只允许输入30个字)&cocos2d-x for wp7&使用cocos2d-x和BOX2D来制作一个BreakOut(打砖块)游戏(一)
编辑:www.fx114.net
本篇文章主要介绍了"&cocos2d-x for wp7&使用cocos2d-x和BOX2D来制作一个BreakOut(打砖块)游戏(一)",主要涉及到&cocos2d-x for wp7&使用cocos2d-x和BOX2D来制作一个BreakOut(打砖块)游戏(一)方面的内容,对于&cocos2d-x for wp7&使用cocos2d-x和BOX2D来制作一个BreakOut(打砖块)游戏(一)感兴趣的同学可以参考一下。
本教程基于子龙山人翻译的cocos2d的IPHONE教程,用cocos2d-x for XNA引擎重写,加上我一些加工制作。教程中大多数文字图片都是原作者和翻译作者子龙山人,还有不少是我自己的理解和加工。感谢原作者的教程和子龙山人的翻译。本教程仅供学习交流之用,切勿进行商业传播。
子龙山人翻译的Iphone教程地址:
Iphone教程原文地址:
程序截图:
box2d是一个非常强大的物理引擎库,同时它与cocos2d-x结合非常适合在window phone上面做游戏开发。著名的angry birds,tiny wings都是用box2d写的。你可以用它做好多事情,当然,最好的学习方法就是使用它来创建一个简单的游戏。
  在这个教程中,我们将一步一步创建一个简单的breakout游戏,完成碰撞检测,篮球反弹物理效果,通过touch拖动paddle(就是上图的白色矩形),以及胜利/失败的场景。
  如果你还不了解cocos2d-x和box2d,你可能先要读一读》以及这些教程。
  好了,是时候制作breakout了!
一个永远反弹的球
打开VS2010。新建一个cocos2d-x项目,命名为cocos2dBox2DBreakOutDemo,并且做好相关的DLL复制和添加。做法可以参照。
然后新建一个类添加到Classes。并且命名为BreakoutScene.cs。
并且添加以下空间引用。
using cocos2d;
using Box2D.XNA;
现在先在这个文件添加一个类BreakOutLayer,并且使之继承于CCLayer。
public static double PTM_RATIO = 32.0;
Body groundB
Fixture bottomF
Fixture ballF
在这些声明里面第一个声明定义比率。这个比率我们在上一个教程中已经讨论过了,这里就不再啰嗦了。
然后重载其init方法。并且修改如下:
public override bool init()
if (!base.init())
CCSize winSize = CCDirector.sharedDirector().getWinSize();
CCLabelTTF title = CCLabelTTF.labelWithString(&Boxing&, &Arial&, 24);
title.position = new CCPoint(winSize.width / 2, winSize.height - 50);
this.addChild(title);
//Create the world
Vector2 gravity = new Vector2(0.0f, 0.0f);
bool doSleep =
world = new World(gravity, doSleep);
//Create edges around the entire screen
BodyDef groundBodyDef = new BodyDef();
groundBodyDef.position = new Vector2(0, 0);
groundBody = world.CreateBody(groundBodyDef);
PolygonShape groundBox = new PolygonShape();
FixtureDef boxShapeDef = new FixtureDef();
boxShapeDef.shape = groundB
groundBox.SetAsEdge(new Vector2(0, 0), new Vector2((float)(winSize.width / PTM_RATIO), 0));
bottomFixture = groundBody.CreateFixture(boxShapeDef);
groundBox.SetAsEdge(new Vector2(0, 0), new Vector2(0, (float)(winSize.height / PTM_RATIO)));
groundBody.CreateFixture(boxShapeDef);
groundBox.SetAsEdge(new Vector2(0, (float)(winSize.height / PTM_RATIO)),
new Vector2((float)(winSize.width / PTM_RATIO), (float)(winSize.height / PTM_RATIO)));
groundBody.CreateFixture(boxShapeDef);
groundBox.SetAsEdge(new Vector2((float)(winSize.width / PTM_RATIO), (float)(winSize.height / PTM_RATIO)),
new Vector2((float)(winSize.width / PTM_RATIO), 0));
groundBody.CreateFixture(boxShapeDef);
好,这个代码和我们上一个教程中,为整个屏幕创建一个盒子边界差不多。然后,这一次,我们把重力设置为0,因为,在我们的breakout游戏中,我们并不需要重力!注意,我们存储了底部的fixture的一个指针,以方便后面使用(在后面的教程中,我们将用来追踪什么时候篮球与顶部相碰撞了)。
现在,下载我制作的,并且添加到Content工程的images文件夹中,让我们往场景里面添加一个精灵吧。紧接着上面的代码,加入下面的代码片段:
//Create sprite and add it to the layer
CCSprite ball = CCSprite.spriteWithFile(@&images/Ball&);
ball.position = new CCPoint(100, 100);
ball.tag = 1;
this.addChild(ball);
  这里没什么疑问,我们已经做过好多次类似的事情了。注意,我们为篮球设置了一个tag标识,后面你会看到,这个tag标记有什么用。
  接下来,为shape创建一个body:
//Create ball body
BodyDef ballBodyDef = new BodyDef();
ballBodyDef.type = BodyType.D
ballBodyDef.position = new Vector2((float)(100 / PTM_RATIO), (float)(100 / PTM_RATIO));
ballBodyDef.userData =
Body ballBody = world.CreateBody(ballBodyDef);
//Create circle shape
CircleShape circle = new CircleShape();
circle._radius = (float)(26.0 / PTM_RATIO);
//Create shape definition and add to body
FixtureDef ballShapeDef = new FixtureDef();
ballShapeDef.shape =
ballShapeDef.density = 1.0f;
ballShapeDef.friction = 0.0f;
ballShapeDef.restitution = 1.0f;
ballFixture = ballBody.CreateFixture(ballShapeDef);
  这个看起来和上一篇教程中的也很像。再巩固一下吧,为了创建一个body对象,我们先要创建一个body定义结构,然后再创建body,接着是shape,再指定fixture结构,最后是创建fixture对象。
  注意,我们设置这些参数有一点点不一样了:我们把回复力(restitution)设置为1.0,这意味着,我们的球在碰撞的时候,将会是完全弹性碰撞。
  同时,我们也保存了球的fixture,原因和我们为什么保存屏幕底部的fixture是一样的,后面你就会看到了。
  更新:注意,我们也把球的摩擦力设置为0.这样可以防止球在碰撞的时候,由于摩擦损失能量,导致来回碰撞的过程中会有一点点偏差。
  好了,是时候做一些完全不同的事了!紧接上面的代码:
Vector2 force = new Vector2(10, 10);
ballBody.ApplyLinearImpulse(force, ballBodyDef.position);
  这里往球上面施加了一个冲力(impulse),这样可以让它初始化的时候朝一个特定的方向运动。
  最后一件事情,就是在init方法中,增加一个tick调度方法:
this.schedule(tick);
下面是tick方法的实现:
void tick(float dt)
world.Step(dt, 10, 10);
for (Body b = world.GetBodyList(); b !=b = b.GetNext() )
if (b.GetUserData() != null)
CCSprite sprite = (CCSprite)b.GetUserData();
sprite.position = new CCPoint((float)(b.GetPosition().X * PTM_RATIO),
(float)(b.GetPosition().Y * PTM_RATIO));
sprite.rotation = -1 * MathHelper.ToDegrees(b.GetAngle());
当然,这里也和上一个教程中的一样,没有什么特别的。
现在,在运行测试之前。还得做些工作。
往BreakOutLayer里面添加一个静态方法来作为初始化层工作。
public static new BreakOutLayer node()
BreakOutLayer layer = new BreakOutLayer();
if (layer.init())
然后让原来没用动过的BreakOutCCScene类继承于CCScene。并且在其构造函数中添加一个BreakOutLayer。
构造函数添加以下代码:
BreakOutLayer layer = BreakOutLayer.node();
this.addChild(layer);
接着修改AppDelegate这个导演类。找到applicationDidFinishLaunching方法。结尾部分修改如下:
// create a scene. it's an autorelease object
//CCScene pScene = cocos2dBox2DBreakOutDemoScene.scene();
Classes.BreakoutScene pScene = new Classes.BreakoutScene();
pDirector.runWithScene(pScene);
好了,让我们试一下吧。编译并运行工程,你将会看到一个球无限地在屏幕里面来回弹!----很酷吧!
增加 Paddle:
如果没有一个paddle的话,那么就不可能称其为一个breakout游戏。下载,并且添加到images文件夹。然后在往BreakOutLayer类中添加下列成员变量:
Body paddleB
Fixture paddleF
然后,在init方法中构建paddle body:
//Create paddle and add it to the layer
CCSprite paddle = CCSprite.spriteWithFile(@&images/Paddle&);
paddle.position = new CCPoint(winSize.width / 2, 50);
this.addChild(paddle);
//Create paddle body
BodyDef paddleBodyDef = new BodyDef();
paddleBodyDef.type = BodyType.D
paddleBodyDef.position = new Vector2((float)(winSize.width / 2 / PTM_RATIO), (float)(50 / PTM_RATIO));
paddleBodyDef.userData =
paddleBody = world.CreateBody(paddleBodyDef);
//Create paddle shape
PolygonShape paddleShape = new PolygonShape();
paddleShape.SetAsBox((float)(paddle.contentSize.width / PTM_RATIO / 2), (float)(paddle.contentSize.height / PTM_RATIO / 2));
//Create shape definition and add to body
FixtureDef paddleShapeDef = new FixtureDef();
paddleShapeDef.shape = paddleS
paddleShapeDef.density = 10.0f;
paddleShapeDef.friction = 0.4f;
paddleShapeDef.restitution = 0.1f;
paddleFixture = paddleBody.CreateFixture(paddleShapeDef);
  我不想花太多的时间解释上面的内容了。因为,和之前的创建篮球的body的过程差不太多。这里只给出不同的地方:
当你创建CCSprite的时候,你并不需要指定精灵的大小。如果你传递一个文件名给它,它会自动计算出大小。 注意,这里不是使用circle shape了。这一次,我们使用polygon shape。我们使用一个辅助方法来创建shape,当然,其形状是个盒子。 我们使用了SetAsBox方法来指定shape相对于body的位置,这个方法在构建复杂的对象的时候比较有用。这里,我们只是让shape在body中间。 我把paddle的密度设置得比球要大得多,同时调节了一下其它的参数。(这些参数要靠试,按照真实的高中物理知识去计算,可能得不到) 同时,我们存储paddleBody和paddleFixture的引用,为了方便后面使用。
  如果你编译并运行的话,你将会看到屏幕中间有一个paddle,而且球碰到它将会反弹。
  然后,这还不是很有趣,因为我们还不能移动paddle!
移动Paddle
  移动paddle需要touch事件,所以先在init方法中允许touch事件:
this.isTouchEnabled =
然后,在BreakOutLayer类中添加下面的成员变量:
MouseJoint mouseJoint =
现在,让我们实现touch方法!首先是ccTouchesBegan:
public override void ccTouchesBegan(List&CCTouch& touches, CCEvent event_)
if (mouseJoint != null)
CCTouch myTouch = touches.FirstOrDefault();
CCPoint location = myTouch.locationInView(myTouch.view());
location = CCDirector.sharedDirector().convertToGL(location);
Vector2 locationWorld = new Vector2((float)(location.x / PTM_RATIO), (float)(location.y / PTM_RATIO));
if (paddleFixture.TestPoint(locationWorld))
MouseJointDef md = new MouseJointDef();
md.bodyA = groundB
md.bodyB = paddleB
md.target = locationW
md.collideConnected =
md.maxForce = 1000.0f * paddleBody.GetMass();
mouseJoint = (MouseJoint)world.CreateJoint(md);
paddleBody.SetAwake(true);
 呃,好多新知识!让我们一点一点来讨论。
  首先,我们把touch坐标转换成coocs2d坐标(convertToGL)然后,再转换成Box2d坐标(locationWorld)。
  然后,我们使用paddle fixture的一个方法来测试这个touch点是否在fixture内部。
  如果是的话,我们就创建一个所谓的”鼠标关节“。在Box2d里面,一个鼠标关节用来让一个body朝着一个指定的点移动---在这里个例子中,就是用户点的方向。
  当你创建一个mouse joint后,你赋值给它两个body。第一个没有被使用,通常都是设置成ground body。第二个,就是你想让它移动的body,在这个例子中就是paddle。
  接下来,你指定移动的终点---这个例子中就是用户点击的位置。
  然后,你告诉box2d,但bodyA和bodyB碰撞的时候,把它当成是碰撞,而不是忽略它。这个很重要!因为,我之前没有设置它为ture,结果不行!因此,当我们用鼠标拖动这个paddle的时候,它并不会与屏幕的边界相碰撞,而且有时候,我的paddle直接就飞出屏幕之外了。这个非常非常奇怪,不过我现在知道是为什么了。因为没有设置bodyA和bodyB是可碰撞的。
  你然后指定移动body的最大的力是多少。如果你减少这个数值的话,paddle body响应鼠标移动时就会慢一些。但是,我们想让paddle快速地响应鼠标的变化。
  最后,我们把这个关节加入到world中,同时,保存这个指针,因为后面有用。同时,我们还要把body设置成苏醒的(awake)。之所以要这么做,是因为如果body在睡觉的话,那么它就不会响应鼠标的移动!
  好了,接下来,让我们添加ccTouchesMoved方法:
public override void ccTouchesMoved(List&CCTouch& touches, CCEvent event_)
if (mouseJoint == null)
CCTouch myTouch = touches.FirstOrDefault();
CCPoint location = myTouch.locationInView(myTouch.view());
location = CCDirector.sharedDirector().convertToGL(location);
Vector2 locationWorld = new Vector2((float)(location.x / PTM_RATIO), (float)(location.y / PTM_RATIO));
mouseJoint.SetTarget(locationWorld);
  这个方法的开头部分和ccTouchesBegan差不多---我们把touch坐标转换成Box2d坐标。唯一的区别就是,我们更新了鼠标关节的目标位置(也就是我们想让paddle移动的位置的)。
  接下来,我们添加ccTouchesCacelled和ccTouchesEnded方法:
public override void ccTouchesCancelled(List&CCTouch& touches, CCEvent event_)
if (mouseJoint != null)
world.DestroyJoint(mouseJoint);
mouseJoint =
public override void ccTouchesEnded(List&CCTouch& touches, CCEvent event_)
if (mouseJoint != null)
world.DestroyJoint(mouseJoint);
mouseJoint =
  我们在这些方法中做的只有一件事,就是在我们移动完paddle或者取消移动之后销毁mouse joint。
  编译并运行,你现在可以用鼠标移动paddle了,同时可以让它与篮球相互碰撞了!
 很好。。。不过,等一下,这还不是一个breakout!我们不可以把paddle移动到任何位置,我们只能在屏幕底部左右来回移动它!
限制Paddle的移动
  我们可以很容易地限制paddle的移动,只需要添加另外一个关节,叫做prismatic joint。这个关节会限制一个body的移动沿着一根指定的轴。
  因此,我们可以使用这种方法来限制paddle相对于地面移动,也就是说只能沿着x轴移动。
  让我们看看相关代码。往init方法中加入下列代码:
//Restrict paddle along the x axis
PrismaticJointDef jointDef = new PrismaticJointDef();
Vector2 worldAxis = new Vector2(1.0f, 0.0f);
jointDef.collideConnected =
jointDef.Initialize(paddleBody, groundBody, paddleBody.GetWorldCenter(), worldAxis);
world.CreateJoint(jointDef);
  第一件事情就是指定一个沿着x轴的向量。然后,我们需要指定collideConnected为true,因此,我们的球才能够正确的反弹,而不是飞到屏幕之外去。
  然后,初始化关节,指定paddle和ground两个body,再使用world对象来创建关节!
  编译并运行,你现在只能沿关x轴方向移动paddle了,这正是我们想要的,不是吧?
完成touch事件
  现在,你玩一下,可能你会发现,有时候球反弹地特别快,有时候又比较慢。这取决于你是如何控制paddle与球相碰撞的。
  原作者理论:我第一次尝试去修正这个bug的时候,我通过直接调整球的速度,使用SetLinearVelocity方法。然后,Steve Oldmeadow也指出,这非常不好!它会破坏物理仿真,最好的方法是通过调用SetLinearDamping方法,间接影响速度。因此,现在这个教程就是这个做的。(damping就是阻尼的意思)
  接下来,在tick方法中添加下列代码,具体位置是在CCSprite sprite = (CCSprite)b.GetUserData();之后:
if (sprite.tag == 1)
int maxSpeed = 10;
Vector2 velocity = b.GetLinearVelocity();
float speed = velocity.Length();
if (speed & maxSpeed)
b.SetLinearDamping(0.5f);
else if (speed & maxSpeed)
b.SetLinearDamping(0.0f);
  这里,我们判断sprite的tag,看是否是球的tag。如果是的话,我们就检查它的速度,如果太大的话,就设置它的阻尼为0.5,这样可以让它慢下来。如果对速度啥的还不满意,可以调节maxSpeed,Damping值
  如果你编译并运行的话,你将会看到一个球以非常适中的速度在屏幕四周来回反弹。
本次工程下载:,这只是一部分,第二部分的教程会包含一个完整的breakout的源码。
版权声明:本文为博主原创文章,未经博主允许不得转载。
一、不得利用本站危害国家安全、泄露国家秘密,不得侵犯国家社会集体的和公民的合法权益,不得利用本站制作、复制和传播不法有害信息!
二、互相尊重,对自己的言论和行为负责。
本文标题:
本页链接:豆丁微信公众号
君,已阅读到文档的结尾了呢~~
扫扫二维码,随身浏览文档
手机或平板扫扫即可继续访问
JBox2D详解-目前网上最全.doc
举报该文档为侵权文档。
举报该文档含有违规或不良信息。
反馈该文档无法正常浏览。
举报该文档为重复文档。
推荐理由:
将文档分享至:
分享完整地址
文档地址:
粘贴到BBS或博客
flash地址:
支持嵌入FLASH地址的网站使用
html代码:
&embed src='http://www.docin.com/DocinViewer-4.swf' width='100%' height='600' type=application/x-shockwave-flash ALLOWFULLSCREEN='true' ALLOWSCRIPTACCESS='always'&&/embed&
450px*300px480px*400px650px*490px
支持嵌入HTML代码的网站使用
您的内容已经提交成功
您所提交的内容需要审核后才能发布,请您等待!
3秒自动关闭窗口}

我要回帖

更多关于 怎么让div并列显示 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信