|   版权声明:本文为博主原创文章,未经博主允许不得转载。

这个是游戏的核心部分:(FlyBird游戏重中之重)

  • 创建一个物理世界(世界设置重力加速度)
  • 在物理世界中添加一个动态的刚体(小鸟)
  • 在物理世界中添加一个静态的刚体(地板)和一个顶部边界(Edge)
  • 在物理世界中添加一对浮动的刚体(Pipe),并设置线速度
  • 设置每次点击屏幕小鸟上升的加速度
  • 碰撞检测,判断游戏是否结束

下面贴上代码:

GamePlay.h

  1. #ifndef _GAME_PLAY_H_
  2. #define _GAME_PLAY_H_
  3.  
  4. #define PTM_RATIO 32
  5.  
  6. #include "cocos2d.h"
  7. #include "Box2D\Box2D.h"
  8. #include "SimpleAudioEngine.h"
  9.  
  10. //背景音乐平台控制
  11. #if (CC_TARGET_PLATFORM == CC_PLATFORM_WINRT)
  12. #define MUSIC_FILE "music/background.wav"
  13. #elif (CC_TARGET_PLATFORM == CC_PLATFORM_BLACKBERRY || CC_TARGET_PLATFORM == CC_PLATFORM_LINUX)
  14. #define MUSIC_FILE "music/background.ogg"
  15. #elif (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
  16. #define MUSIC_FILE "music/background.caf"
  17. #else
  18. #define MUSIC_FILE "music/background.mp3"
  19. #endif // CC_PLATFOR_WIN32
  20.  
  21. USING_NS_CC;
  22. using namespace CocosDenshion;
  23.  
  24. class GamePlay : public cocos2d::Layer, public b2ContactListener
  25. {
  26. private:
  27. cocos2d::Sprite* backgroundA;
  28. cocos2d::Sprite* backgroundB;
  29. cocos2d::Sprite* ready;
  30. cocos2d::Sprite* tutorial;
  31. cocos2d::Sprite* bird;
  32. cocos2d::Sprite* land;
  33. cocos2d::Sprite* num;
  34. cocos2d::Sprite* upPipe;
  35. cocos2d::Sprite* downPipe;
  36. cocos2d::Sprite* pipeContainer;
  37. cocos2d::Sprite* model;
  38. cocos2d::Sprite* gameEnd;
  39. cocos2d::LabelTTF* score;
  40. cocos2d::LabelTTF* best;
  41. cocos2d::MenuItemImage* play;
  42. cocos2d::MenuItemImage* exit;
  43. b2World* world;
  44. b2Body* birdBody;
  45. b2Body* landBody;
  46. b2Body* downBody;
  47. b2Body* upBody;
  48. int bestScore;
  49. int times = 0;
  50.  
  51. private:
  52. void replaceBackground(int);
  53. void tipInformation();
  54. void addBird();
  55. void addLand();
  56. void addPipe(float dt);
  57. void gameBegin(float dt);
  58. void gameOver();
  59. void timeAnimate();
  60. void upperBoundary();
  61. //int birdSelect(float);
  62.  
  63. public:
  64. static cocos2d::Scene* createScene();
  65. virtual bool init();
  66. void initPhysicsWorld();
  67. virtual void update(float);
  68. /// Called when two fixtures begin to touch.
  69. virtual void BeginContact(b2Contact* contact);
  70. /** Callback function for multiple touches began.
  71. *
  72. * @param touches Touches information.
  73. * @param unused_event Event information.
  74. * @js NA
  75. */
  76. virtual void onTouchesBegan(const std::vector<Touch*>& touches, Event *unused_event);
  77. void goPlay(cocos2d::Ref* pSender);
  78. void goExit();
  79. CREATE_FUNC(GamePlay);
  80. };
  81.  
  82. #endif // _GAME_PLAY_H_

 GamePlay.cpp

  1. #include "GamePlay.h"
  2. #include "GameUnit.h"
  3. #include "GameData.h"
  4.  
  5. unit u3;
  6.  
  7. cocos2d::Scene* GamePlay::createScene()
  8. {
  9. auto scene = Scene::create();
  10. auto layer = GamePlay::create();
  11. scene->addChild(layer);
  12. return scene;
  13. }
  14.  
  15. bool GamePlay::init()
  16. {
  17. if (!Layer::init())
  18. {
  19. return false;
  20. }
  21. SimpleAudioEngine::getInstance()->playBackgroundMusic(MUSIC_FILE, true);
  22. this->initPhysicsWorld();
  23. this->replaceBackground(1);
  24. this->tipInformation();
  25. this->upperBoundary();
  26. this->addLand();
  27. this->addBird();
  28. this->timeAnimate();
  29. //this->addPipe();
  30.  
  31. //设置多点触屏事件的监听器
  32. auto listener = EventListenerTouchAllAtOnce::create();
  33. listener->onTouchesBegan = CC_CALLBACK_2(GamePlay::onTouchesBegan, this);
  34. //注册监听器
  35. _eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this);
  36.  
  37. //设置物理世界监听
  38. world->SetContactListener(this);
  39.  
  40. scheduleOnce(schedule_selector(GamePlay::gameBegin), 3);
  41. //scheduleUpdate();
  42.  
  43. return true;
  44. }
  45.  
  46. void GamePlay::initPhysicsWorld()
  47. {
  48. //设置重力加速度为9.8;方向向下
  49. b2Vec2 gravity;
  50. gravity.Set(0.0f, -9.8f);
  51. //创建一个新的物理世界
  52. world = new b2World(gravity);
  53.  
  54. //设置是否允许物体休眠
  55. world->SetAllowSleeping(true);
  56. //连续物理测试,防止发生非子弹特性的物体发生穿透现象
  57. world->SetContinuousPhysics(true);
  58. }
  59.  
  60. void GamePlay::timeAnimate()
  61. {
  62. num = Sprite::create("bird/n1.png");
  63. num->setPosition(Vec2(u3.winOrigin().x + u3.winSize().width / 2,
  64. u3.winOrigin().y + (4 * u3.winSize().height) / 5));
  65. num->setScale(2);
  66. auto repeat = Repeat::create(Animate::create(u3.gameAnimate(4)), 1);
  67. num->runAction(repeat);
  68. this->addChild(num, 1);
  69. }
  70.  
  71. void GamePlay::replaceBackground(int flag)
  72. {
  73. switch (flag)
  74. {
  75. case 1:
  76. backgroundA = Sprite::create("background/light.png");
  77. backgroundA->setPosition(Vec2(u3.winOrigin().x + u3.winSize().width / 2,
  78. u3.winOrigin().y + u3.winSize().height / 2));
  79. backgroundA->setScale(u3.scaleX(backgroundA, u3.winSize()),
  80. u3.scaleY(backgroundA, u3.winSize()));
  81. this->addChild(backgroundA, 0);
  82. break;
  83. case 2:
  84. backgroundB = Sprite::create("background/night.png");
  85. backgroundB->setPosition(Vec2(u3.winOrigin().x + u3.winSize().width / 2,
  86. u3.winOrigin().y + u3.winSize().height / 2));
  87. backgroundB->setScale(u3.scaleX(backgroundB, u3.winSize()),
  88. u3.scaleY(backgroundB, u3.winSize()));
  89. this->addChild(backgroundB, 0);
  90. break;
  91. default:
  92. break;
  93. }
  94. }
  95.  
  96. void GamePlay::tipInformation()
  97. {
  98. ready = Sprite::create("logo/text_ready.png");
  99. ready->setPosition(Vec2(u3.winOrigin().x + u3.winSize().width / 2,
  100. u3.winOrigin().y + u3.winSize().height - 3*ready->getContentSize().height));
  101. ready->setScale(2);
  102. this->addChild(ready, 1);
  103.  
  104. tutorial = Sprite::create("logo/tutorial.png");
  105. tutorial->setPosition(Vec2(u3.winOrigin().x + u3.winSize().width / 2,
  106. u3.winOrigin().y + u3.winSize().height / 2));
  107. tutorial->setScale(2);
  108. this->addChild(tutorial, 1);
  109.  
  110. //exit
  111. exit = MenuItemImage::create(
  112. "button/exit_f.png",
  113. "button/exit_b.png",
  114. CC_CALLBACK_0(GamePlay::goExit, this)
  115. );
  116. Menu* menu = Menu::create(exit, NULL);
  117. menu->setPosition(Vec2(u3.winOrigin().x + exit->getContentSize().width / 2,
  118. u3.winOrigin().y + exit->getContentSize().height / 2));
  119. this->addChild(menu, 7);
  120. }
  121.  
  122. void GamePlay::addBird()
  123. {
  124. bird = Sprite::create("bird/littleBird.png");
  125. bird->setPosition(Vec2(u3.winOrigin().x + u3.winSize().width / 3,
  126. u3.winOrigin().y + u3.winSize().height - 5 * (ready->getContentSize().height)));
  127. bird->setScale(1.5);
  128. auto repeat = RepeatForever::create(Animate::create(u3.gameAnimate(1)));
  129. bird->runAction(repeat);
  130. this->addChild(bird, 1);
  131.  
  132. //创建刚体
  133. b2BodyDef birdBodyDef;
  134. birdBodyDef.type = b2_dynamicBody;
  135. birdBodyDef.position.Set(bird->getPosition().x / PTM_RATIO,
  136. bird->getPosition().y / PTM_RATIO);
  137. //将刚体,精灵与世界关联起来
  138. birdBody = world->CreateBody(&birdBodyDef);
  139. birdBody->SetUserData(bird);
  140.  
  141. //定义一个盒子
  142. b2PolygonShape birdBox;
  143. birdBox.SetAsBox(bird->getContentSize().width / 3 / PTM_RATIO,
  144. bird->getContentSize().height / 3 / PTM_RATIO);
  145. //夹具
  146. b2FixtureDef fixtureDef;
  147. //设置夹具的形状
  148. fixtureDef.shape = &birdBox;
  149. birdBody->CreateFixture(&fixtureDef);
  150. }
  151.  
  152. void GamePlay::update(float dt)
  153. {
  154. world->Step(dt, 8, 3);
  155. for (b2Body* bb = world->GetBodyList(); bb; bb = bb->GetNext())
  156. {
  157. if (bb->GetUserData() != nullptr)
  158. {
  159. Sprite* sprite = (Sprite*)bb->GetUserData();
  160. //设置精灵的当前的位置,通过取得精灵的位置乘上相应的像素,这里的PTM_RATIO为32个像素为1m,就可以判断出精灵的位置处于物理世界的何处
  161. sprite->setPosition(Vec2(bb->GetPosition().x*PTM_RATIO,
  162. bb->GetPosition().y*PTM_RATIO));
  163. //设置精灵的角度偏转
  164. sprite->setRotation(0);
  165. }
  166. }
  167. }
  168.  
  169. void GamePlay::onTouchesBegan(const std::vector<Touch*>& touches, Event *unused_event)
  170. {
  171. birdBody->SetLinearVelocity(b2Vec2(0, 5));
  172. //birdBody->SetLinearVelocity(b2Vec2(1, 5));
  173. }
  174.  
  175. //添加地面
  176. void GamePlay::addLand()
  177. {
  178. //地板也是物理世界的一个刚体,是一个静态的刚体
  179. land = Sprite::create("background/land.png");
  180. land->setPosition(Vec2(u3.winOrigin().x + u3.winSize().width / 2,
  181. u3.winOrigin().y + land->getContentSize().height / 2));
  182. land->setScaleX(u3.winSize().width / 1.5*land->getContentSize().width);
  183. land->setScaleY(u3.winSize().height / (land->getContentSize().height * 3));
  184. this->addChild(land, 4);
  185.  
  186. //创建刚体
  187. b2BodyDef landBodyDef;
  188. landBodyDef.type = b2_staticBody;
  189. landBodyDef.position.Set(u3.winSize().width / 2 / PTM_RATIO,
  190. land->getPosition().y / PTM_RATIO);
  191.  
  192. landBody = world->CreateBody(&landBodyDef);
  193. landBody->SetUserData(land);
  194.  
  195. b2PolygonShape landShape;
  196. landShape.SetAsBox(u3.winSize().width / 2 / PTM_RATIO,
  197. backgroundA->getContentSize().height / 2 / PTM_RATIO);
  198. //1.4*land->getContentSize().height / PTM_RATIO
  199. b2FixtureDef landFixtureDef;
  200. landFixtureDef.shape = &landShape;
  201. landBody->CreateFixture(&landFixtureDef);
  202. }
  203.  
  204. void GamePlay::upperBoundary()
  205. {
  206. b2BodyDef upperBodyDef;
  207. //左下角
  208. upperBodyDef.position.Set(0, 0);
  209. //创建地面物体
  210. b2Body* upperBody = world->CreateBody(&upperBodyDef);
  211. //定义一个有边的形状
  212. b2EdgeShape upperBox;
  213.  
  214. //顶部边界线
  215. upperBox.Set(b2Vec2(0, u3.winSize().height / PTM_RATIO),
  216. b2Vec2(u3.winSize().width / PTM_RATIO, u3.winSize().height / PTM_RATIO));
  217. upperBody->CreateFixture(&upperBox, 0);
  218. }
  219.  
  220. void GamePlay::addPipe(float dt)
  221. {
  222. times++;
  223.  
  224. float randPipe = -rand() % 3;
  225. //down bar
  226. downPipe = Sprite::create("pipe/down.png");
  227. downPipe->setScaleY(u3.winSize().height / (downPipe->getContentSize().height*1.5));
  228. this->addChild(downPipe, 3);
  229. b2BodyDef downBodyDef;
  230. downBodyDef.position = b2Vec2(u3.winSize().width / PTM_RATIO + 2,
  231. downPipe->getContentSize().height / 2 / PTM_RATIO + randPipe);
  232. // + land->getContentSize().height / PTM_RATIO
  233. downBodyDef.type = b2_kinematicBody;
  234. //修改速度可以提升游戏的难度
  235. downBodyDef.linearVelocity = b2Vec2(-2, 0);
  236. downBody = world->CreateBody(&downBodyDef);
  237. downBody->SetUserData(downPipe);
  238. b2PolygonShape downShape;
  239. downShape.SetAsBox(downPipe->getContentSize().width / 2 / PTM_RATIO,
  240. 1.6*downPipe->getContentSize().height / PTM_RATIO);
  241. b2FixtureDef downPipeFixture;
  242. downPipeFixture.shape = &downShape;
  243. downBody->CreateFixture(&downPipeFixture);
  244.  
  245. upPipe = Sprite::create("pipe/upPipe.png");
  246. upPipe->setScaleY(u3.winSize().height / (upPipe->getContentSize().height*1.5));
  247. this->addChild(upPipe, 3);
  248. b2BodyDef upBodyDef;
  249. upBodyDef.position = b2Vec2(u3.winSize().width / PTM_RATIO + 2,
  250. downPipe->getContentSize().height / PTM_RATIO + randPipe + 3 +2*upPipe->getContentSize().height / PTM_RATIO);
  251. //
  252. upBodyDef.type = b2_kinematicBody;
  253. //修改速度可以提升游戏的难度
  254. upBodyDef.linearVelocity = b2Vec2(-2, 0);
  255. upBody = world->CreateBody(&upBodyDef);
  256. upBody->SetUserData(upPipe);
  257. b2PolygonShape upShape;
  258. upShape.SetAsBox(upPipe->getContentSize().width / 2 / PTM_RATIO,
  259. 1.6*upPipe->getContentSize().height / PTM_RATIO);
  260. b2FixtureDef upPipeFixture;
  261. upPipeFixture.shape = &upShape;
  262. upBody->CreateFixture(&upPipeFixture);
  263. }
  264.  
  265. void GamePlay::gameOver()
  266. {
  267. //显示Game Over的Logo
  268. gameEnd = Sprite::create("logo/gameOver.png");
  269. gameEnd->setPosition(Vec2(u3.winOrigin().x + u3.winSize().width / 2,
  270. u3.winOrigin().y + u3.winSize().height - 3*gameEnd->getContentSize().height));
  271. gameEnd->setScale(2);
  272. this->addChild(gameEnd, 5);
  273.  
  274. //显示奖章牌
  275. model = Sprite::create("logo/score_panel.png");
  276. model->setPosition(Vec2(u3.winOrigin().x + u3.winSize().width / 2,
  277. u3.winOrigin().y + u3.winSize().height / 2));
  278. model->setScale(u3.winSize().width / 1.5 / model->getContentSize().width,
  279. u3.winSize().height / 4.5 / model->getContentSize().height);
  280. this->addChild(model, 5);
  281.  
  282. //奖章
  283. Sprite* award = Sprite::create("logo/medals1.png");
  284. award->setPosition(Vec2(u3.winOrigin().x + u3.winSize().width / 2 - model->getContentSize().width*0.6,
  285. u3.winOrigin().y + u3.winSize().height / 2));
  286. award->setScale(3);
  287. this->addChild(award, 6);
  288.  
  289. //显示成绩
  290. score = LabelTTF::create("0", "Arial", 16);
  291. score->setPosition(Vec2(u3.winOrigin().x + (u3.winSize().width / 3) * 2,
  292. u3.winOrigin().y + u3.winSize().height / 2 + award->getContentSize().height));
  293. this->addChild(score, 7);
  294. //设置字体的颜色为黑色,并将成绩显示在panel面板上
  295. score->setColor(Color3B(0, 0, 0));
  296. score->setString(__String::createWithFormat("%5d", times - 1)->getCString());
  297.  
  298. bestScore = GameData::getGameData();
  299. best = LabelTTF::create("0", "Arial", 16);
  300. best->setPosition(Vec2(u3.winOrigin().x + (u3.winSize().width / 3) * 2,
  301. u3.winOrigin().y + u3.winSize().height / 2 - 1.5*award->getContentSize().height));
  302. this->addChild(best, 7);
  303. best->setColor(Color3B(0, 0, 0));
  304. best->setString(__String::createWithFormat("%5d", bestScore - 1)->getCString());
  305. GameData::keepGameData(times);
  306.  
  307. unscheduleUpdate();
  308. unschedule(schedule_selector(GamePlay::addPipe));
  309. }
  310.  
  311. void GamePlay::gameBegin(float dt)
  312. {
  313. ready->setVisible(false);
  314. tutorial->setVisible(false);
  315. num->setVisible(false);
  316.  
  317. scheduleUpdate();
  318. //修改时间可以提升游戏的难易程度
  319. schedule(schedule_selector(GamePlay::addPipe), 2);
  320. }
  321.  
  322. void GamePlay::BeginContact(b2Contact* contact)
  323. {
  324. if (contact->GetFixtureA()->GetBody() == birdBody || contact->GetFixtureB()->GetBody() == birdBody)
  325. {
  326. this->gameOver();
  327.  
  328. play = MenuItemImage::create(
  329. "button/play.png",
  330. "button/play.png",
  331. CC_CALLBACK_1(GamePlay::goPlay, this)
  332. );
  333. play->setPosition(Vec2(u3.winOrigin().x + u3.winSize().width / 2,
  334. u3.winOrigin().y + u3.winSize().height / 3));
  335. Menu* menu = Menu::create(play, NULL);
  336. menu->setPosition(Vec2::ZERO);
  337. menu->setScale(1.5);
  338. this->addChild(menu, 6);
  339. }
  340. }
  341.  
  342. void GamePlay::goPlay(cocos2d::Ref* pSender)
  343. {
  344. times = 0;
  345. Director::getInstance()->replaceScene(TransitionFadeTR::create(1,
  346. GamePlay::createScene()));
  347. }
  348.  
  349. void GamePlay::goExit()
  350. {
  351. times = 0;
  352. unscheduleUpdate();
  353. unschedule(schedule_selector(GamePlay::addPipe));
  354.  
  355. Director::getInstance()->end();
  356. }

函数功能详见:http://www.cnblogs.com/geore/p/5800009.html

效果图:

Cocos2d 之FlyBird开发---GamePlay类的更多相关文章

  1. Cocos2d 之FlyBird开发---MainMenu类

    |   版权声明:本文为博主原创文章,未经博主允许不得转载. MainMenu类主要实现的是游戏主界面的布局,它相当于一个港口,有开向各处的航道,而游戏中的MainMenu则是有跳转到各个场景的一个集 ...

  2. Cocos2d 之FlyBird开发---GameUnit类

    |   版权声明:本文为博主原创文章,未经博主允许不得转载. 这节来实现GameUnit类中的一些函数方法,其实这个类一般是一个边写边完善的过程,因为一般很难一次性想全所有的能够供多个类共用的方法.下 ...

  3. Cocos2d 之FlyBird开发---GameData类

    |   版权声明:本文为博主原创文章,未经博主允许不得转载. 现在是大数据的时代,绝大多数的游戏也都离不开游戏数据的控制,简单的就是一般记录游戏的得分情况,高端大气上档次一点的就是记录和保存各方面的游 ...

  4. Cocos2d 之FlyBird开发---GameScore类

    |   版权声明:本文为博主原创文章,未经博主允许不得转载. 这个类主要实现的是,显示历次成绩中的最好成绩.当然我写的这个很简洁,还可以写的更加的丰富.下面贴上代码: GameScore.h #ifn ...

  5. Cocos2d 之FlyBird开发---GameAbout类

    |   版权声明:本文为博主原创文章,未经博主允许不得转载.(笔者才疏学浅,如有错误,请多多指教) 一般像游戏关于的这种界面中,主要显示的是游戏的玩法等. GameAbout.h #ifndef _G ...

  6. Cocos2d之FlyBird开发---简介

    |   版权声明:本文为博主原创文章,未经博主允许不得转载. 开发FlyBird其实非常的简单,在游戏的核心部分,我们需要实现的只有: 创建一个物理世界(世界设置重力加速度) 在物理世界中添加一个动态 ...

  7. JAVA串口开发帮助类分享-及写在马年末

    摘要: 在系统集成开发过程中,存在着各式的传输途径,其中串口经常因其安全性高获得了数据安全传输的重用,通过串口传输可以从硬件上保证数据传输的单向性,这是其它介质所不具备的物理条件.下面我就串口java ...

  8. iOS cocos2d 2游戏开发实战(第3版)书评

    2013是游戏爆发的一年,手游用户也是飞速暴增.虽然自己不做游戏,但也是时刻了解手机应用开发的新动向.看到CSDN的"写书评得技术图书赢下载分"活动,就申请了一本<iOS c ...

  9. (转载)实例详解Android快速开发工具类总结

    实例详解Android快速开发工具类总结 作者:LiJinlun 字体:[增加 减小] 类型:转载 时间:2016-01-24我要评论 这篇文章主要介绍了实例详解Android快速开发工具类总结的相关 ...

随机推荐

  1. sqlserver创建索引语句

    CREATE INDEX PersonIndex ON 表名 (字段名)   DROP INDEX PersonIndex ON 表名

  2. git 命令图解

    git 命令图解   初始化版本库 git config user.name "lsgx" git config user.email "lsgxthink@163.co ...

  3. 20191114PHP验证码

    <?phpob_clean();$img=imagecreate(40,20);$back=imagecolorallocate($img,200,200,200); $blue=imageco ...

  4. Ubuntu系统安装配置tensorflow开发环境

    Ubuntu系统安装 下载ubuntu iso 选择目前最新的版本是 Ubuntu 18.04 LTS .下载地址: 官网:https://www.ubuntu.com/download/deskto ...

  5. 安卓构架组件——向项目添加组件(Adding Components to your Project)

    在开始之前,建议阅读 应用架构指南. Before getting started, we recommend reading the Architecture Components Guide to ...

  6. 形象生动的SpringBoot和SpringMVC的区别

    spring boot只是一个配置工具,整合工具,辅助工具. springmvc是框架,项目中实际运行的代码 Spring 框架就像一个家族,有众多衍生产品例如 boot.security.jpa等等 ...

  7. shell简单的菜单功能

  8. smbcontrol - 向smbd或nmbd进程发送消息

    总览smbcontrol [ -i ] smbcontrol [ 目标 ] [ 消息类型 ] [ 参数 ] 描述这个工具是是Samba组件的一部分. smbcontrol是个很小的程序,用它可以向系统 ...

  9. MyEclipse创建maven项目时报: org.apache.maven.archiver.MavenArchiver.getManifest 错误

    创建项目报错,如图: 原因就是maven的配置文件不是最新的,MyEclipse2014解决方法: 1.help ->Install New sitie... 2.点击add 3.填写name和 ...

  10. Shell05--函数应用

    目录 Shell05---函数应用 1. 函数基本概述 2. 函数基本使用 3. 函数参数传递 4. 函数状态返回 5. 函数场景示例 Shell05---函数应用 1. 函数基本概述 01. 什么是 ...