现在的位置: 首页 > 综合 > 正文

(转)Cocos2d-x加Box2D制作弹弓类游戏

2013年02月02日 ⁄ 综合 ⁄ 共 5465字 ⁄ 字号 评论关闭
原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 、作者信息和本声明。否则将追究法律责任。http://mssyy2010.blog.51cto.com/4595971/847000

文章原版为英文版,地址链接在文章尾部给出。原文代码版本为object-c版,本文代码版本为C++版。对原文大部分内容进行了翻译,并将对oc版的说明更改为C++版。文章cocos2d-x版本cocos2d-1.0.1-x-0.11.0。

如何用Box2D和cocos2d-x制作弹弓类游戏 第一部分

这是一篇由ios教程团队成员Gustavo Ambrozio上传的博客。一位拥有超过20年软件开发经验,超过3年ios开发经验的软件工程师,CodeCrop软件创始人。

在这个教程系列中我们将会通过使用cocos2d-x和Box2D创建一个很COOL的弹弓类型游戏。

我们将使用Ray的可爱而富有天赋的老婆Vicki创作的弹弓,栗子,狗,猫和愤怒的松鼠素材来创建游戏。(素材我会在上传附件)

 

在这个教程系列,你将学到:

  • 怎么用旋转关节(rotation joints)
  • 怎么用连接关节(weld joints)
  • 怎么让视角跟随抛射物
  • 怎么根据碰撞检测判断力量来消除敌人
  • 和很多其他的

 

这个教程系列假设你已经掌握了  Intro to Box2D with Cocos2D Tutorial: Bouncing Balls Tutorial或者已经掌握了相关知识。

教程中还会使用很多制作撞球游戏中的概念。

 

开始吧

新建HelloWorld项目,清空项目。记得选择需要Box2d支持的cocos2d-x工程。声明一个catapult类。和HelloWorld类除了名字全都一样。

 

加入些精灵

 

首先我们先添加项目将用的资源。

现在我们来加入些不会被物理模拟的精灵。默认的CCSprite的锚点是中心,我将锚点改到了左下角为了更容易的放置它们。

在init方法中// add your codes below...下面添加代码:

  1. CCSprite *sprite = CCSprite::spriteWithFile("bg.png");  //背景图 
  2.         sprite->setAnchorPoint(CCPointZero); 
  3.         this->addChild(sprite, -1); 
  4.      
  5.         CCSprite *sprite = CCSprite::spriteWithFile("catapult_base_2.png"); //投射器底部后面那块 
  6.         sprite->setAnchorPoint(CCPointZero); 
  7.         sprite->setPosition(CCPointMake(181.0, FLOOR_HEIGHT)); 
  8.         this->addChild(sprite, 0); 
  9.      
  10.         sprite = CCSprite::spriteWithFile("squirrel_1.png");        //左边松鼠 
  11.         sprite->setAnchorPoint(CCPointZero); 
  12.         sprite->setPosition(CCPointMake(11.0, FLOOR_HEIGHT)); 
  13.         this->addChild(sprite, 0); 
  14.      
  15.         sprite = CCSprite::spriteWithFile("catapult_base_1.png");   //投射器底部前面那块 
  16.         sprite->setAnchorPoint(CCPointZero); 
  17.         sprite->setPosition(CCPointMake(181.0, FLOOR_HEIGHT)); 
  18.         this->addChild(sprite, 9); 
  19.      
  20.         sprite = CCSprite::spriteWithFile("squirrel_2.png");    //右边松鼠 
  21.         sprite->setAnchorPoint(CCPointZero); 
  22.         sprite->setPosition(CCPointMake(240.0, FLOOR_HEIGHT)); 
  23.         this->addChild(sprite, 9); 
  24.      
  25.         sprite = CCSprite::spriteWithFile("fg.png");    //带冰的地面 
  26.         sprite->setAnchorPoint(CCPointZero); 
  27.         this->addChild(sprite, 10); 

你也许注意到了很多使用Y坐标的地方用了宏FLOOR_HEIGHT,但我们并未define它。

  1. #define FLOOR_HEIGHT    62.0f 

定义了这个宏之后,如果我们改变了地板高度,我们可以更加简便的放置精灵。

上效果图。

看起来不错!

上面就是非物理模拟的部分。

 

 

增加弹弓臂

是时候给世界加些物理属性了,接下来的代码就是加世界边框的模板式的代码了,让我们改变一点来描述我们的世界。

类声明中添加:

  1. private
  2.     b2World* m_world; 
  3.     b2Body* m_groundBody; 

init方法尾部添加:

  1. b2Vec2 gravity; 
  2. gravity.Set(0.0f, -10.0f); 
  3. bool doSleep = true
  4. m_world = new b2World(gravity); 
  5. m_world->SetAllowSleeping(doSleep); 
  6. m_world->SetContinuousPhysics(true); 
  7.  
  8. // Define the ground body. 
  9. b2BodyDef groundBodyDef; 
  10. groundBodyDef.position.Set(0, 0); // bottom-left corner 
  11.  
  12. // Call the body factory which allocates memory for the ground body 
  13. // from a pool and creates the ground box shape (also from a pool). 
  14. // The body is also added to the world. 
  15. m_groundBody = m_world->CreateBody(&groundBodyDef); 

默认是世界的尺寸是iphone屏幕尺寸。因为我们场景的宽度是世界宽度的2被。完成这个任务我们只需要让宽度乘以1.5.

另外,由于我们世界的地板并不是在屏幕的底部,所以我们需要编写相应的代码。

边界代码:

  1. b2EdgeShape groundBox; 
  2.     // bottom 
  3.     groundBox.Set(b2Vec2(0,FLOOR_HEIGHT/PTM_RATIO), b2Vec2(screenSize.width*2.0f/PTM_RATIO,FLOOR_HEIGHT/PTM_RATIO)); 
  4.     m_groundBody->CreateFixture(&groundBox, 0); 
  5.      
  6.     // top 
  7.     groundBox.Set(b2Vec2(0,screenSize.height/PTM_RATIO), b2Vec2(screenSize.width*2.0f/PTM_RATIO,screenSize.height/PTM_RATIO)); 
  8.     m_groundBody->CreateFixture(&groundBox, 0); 
  9.      
  10.     // left 
  11.     groundBox.Set(b2Vec2(0,screenSize.height/PTM_RATIO), b2Vec2(0,0)); 
  12.     m_groundBody->CreateFixture(&groundBox, 0); 
  13.      
  14.     // right 
  15.     groundBox.Set(b2Vec2(screenSize.width*1.5f/PTM_RATIO,screenSize.height/PTM_RATIO), b2Vec2(screenSize.width*1.5f/PTM_RATIO,0)); 
  16.     m_groundBody->CreateFixture(&groundBox, 0); 

说明:box2d某次更新后以前的SetAsEdge函数被删除了,但是可以使用b2EdgeShape类型对象来生成边界,函数名也变为Set。

现在让我们增加弹弓臂,首先增加物体(body)和夹具(fixture)的指针。打开HelloWorld.h把下面的代码加入到类中。

  1. private
  2.     b2Fixture *m_armFixture; 
  3.     b2Body *m_armBody; 

进入到HelloWorld.cpp文件中的init函数的底部:

  1. // Create the catapult's arm 
  2.     CCSprite *arm = CCSprite::spriteWithFile("catapult_arm.png"); 
  3.     this->addChild(arm, 1); 
  4.      
  5.     b2BodyDef armBodyDef; 
  6.     armBodyDef.type = b2_dynamicBody; 
  7.     armBodyDef.linearDamping = 1; 
  8.     armBodyDef.angularDamping = 1; 
  9.     armBodyDef.position.Set(230.0f/PTM_RATIO, (FLOOR_HEIGHT+91.0f)/PTM_RATIO); 
  10.     armBodyDef.userData = arm; 
  11.     m_armBody = m_world->CreateBody(&armBodyDef); 
  12.      
  13.     b2PolygonShape armBox; 
  14.     b2FixtureDef armBoxDef; 
  15.     armBoxDef.shape = &armBox; 
  16.     armBoxDef.density = 0.3F; 
  17.     armBox.SetAsBox(11.0f/PTM_RATIO, 91.0f/PTM_RATIO); 
  18.     m_armFixture = m_armBody->CreateFixture(&armBoxDef); 

 

 

你如果看过之前的Box2D教程那么这些代码对你而言应该很熟悉。

我们先读取弹弓臂精灵并把它加入到层中。注意z轴索引。当我们向scene中加入静态精灵时候我们使用Z轴索引。

让我们的弹弓臂位于2块弹弓底部之间看起来不错!

类声明中增加:

  1. void tick(cocos2d::ccTime dt); 

cpp文件增加:

  1. void HelloWorld::tick(ccTime dt) 
  2.     int velocityIterations = 8; 
  3.     int positionIterations = 1; 
  4.  
  5.     m_world->Step(dt, velocityIterations, positionIterations); 
  6.  
  7.     //Iterate over the bodies in the physics world 
  8.     for (b2Body* b = m_world->GetBodyList(); b; b = b->GetNext()) 
  9.     { 
  10.         if (b->GetUserData() != NULL) { 
  11.             //Synchronize the AtlasSprites position and rotation with the corresponding body 
  12.             CCSprite* myActor = (CCSprite*)b->GetUserData(); 
  13.             myActor->setPosition( CCPointMake( b->GetPosition().x * PTM_RATIO, b->GetPosition().y * PTM_RATIO) ); 
  14.             myActor->setRotation( -1 * CC_RADIANS_TO_DEGREES(b->GetAngle()) ); 
  15.         }    
  16.     } 
  17. }

在init方法尾部加入:

  1. schedule(schedule_selector(Catapult::tick)); 

看到没?我们并没有设置精灵的位置,因为tick方法会更正精灵的位置到box2D物体的位置。

接下来我们创建

抱歉!评论已关闭.