flappy bird游戏源代码揭秘和下载

转:http://blog.csdn.net/touchsnow/article/details/19071961

背景:

最近火爆全球的游戏flappy bird让笔者叹为观止,于是花了一天的时间山寨了一个一模一样的游戏,现在把游戏的思路和源码分享出来,代码是基于javascript语言,cocos2d-x游戏引擎,cocos2d-x editor手游开发工具完成的,请读者轻砸;

ps:运行demo必须配置好cocos2d-x editor,暂不支持其他工具。还有demo是跨平台的,可移植运行android,ios,html5移动系统等;

Android Apk下载:(演示效果)

暂时只移植打包到android系统,可下载运行看看效果;

腾讯微云:http://share.weiyun.com/cac18d8c58d40bf2401b3fdeeb6bcb2f

代码下载:

代码*免费下载:  http://blog.makeapp.co/?p=306&preview=true

csdn下载:http://download.csdn.net/detail/touchsnow/6912707

百度云盘:http://pan.baidu.com/s/1pJnWDb9

金山快盘 :http://www.kuaipan.cn/file/id_25348935635745384.htm?source=1

代码如何移植到各平台:

 Android:http://blog.csdn.net/touchsnow/article/details/19176091

html5:       http://blog.makeapp.co/?p=245

效果图:

flappy bird游戏源代码揭秘和下载

flappy bird游戏源代码揭秘和下载

flappy bird游戏源代码揭秘和下载

cocos2d-x跨平台游戏引擎
 
cocos2d-x是全球知名的游戏引擎 ,引擎在全球范围内拥有众多开发者,涵盖国内外各知名游戏开发商。目前Cocos2d-x引擎已经实现横跨ios、Android、Bada、MeeGo、BlackBerry、Marmalade、Windows、Linux等平台。编写一次,到处运行,分为两个版本 cocos2d-c++和cocos2d-html5 本文使用了后者;
cocos2d-x 官网:http://cocos2d-x.org/
cocos2d-x 资料下载  http://cocos2d-x.org/download

cocos2d-x editor开发工具:

cocos2dx editor,它是开发跨平台的手机游戏工具,运行window/mac系统上,javascript脚本语言,基于cocos2d-x跨平台游戏引擎, 集合代码编辑,场景设计,动画制作,字体设计,还有粒子,物理系统,地图等等的,而且调试方便,和实时模拟;

cocos2dx editor 下载,介绍和教程:http://blog.csdn.net/touchsnow/article/details/19070665

cocos2dx editor官方博客:http://blog.makeapp.co/;(请持续关注版本更新)

思路和源码:

1 场景设计MainLayer.ccbx,如下图;主要分三层,开始场景、主场景、游戏结束场景,通过显示隐藏控制三个场景的切换。

flappy bird游戏源代码揭秘和下载

MainLayer.ccbx代码

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <Document
  3. jsControlled="true"
  4. jsController="MainLayer"
  5. resolution="default"
  6. >
  7. <Resolutions>
  8. <Resolution centeredOrigin="false" ext="iphone" height="1280" width="720" name="default" scale="1"/>
  9. <Resolution centeredOrigin="false" ext="iphone" height="720" width="1280" name="default1" scale="1"/>
  10. </Resolutions>
  11. <Animations>
  12. <Animation autoPlay="true"
  13. id="0"
  14. name="Default Timeline"
  15. length="10"
  16. chainedId="0"
  17. offset="0.0"
  18. position="0.0"
  19. resolution="30"
  20. scale="128">
  21. <CallbackChannel>
  22. </CallbackChannel>
  23. <SoundChannel>
  24. </SoundChannel>
  25. </Animation>
  26. </Animations>
  27. <Layer
  28. positionX="0" positionY="0.0"
  29. sizeType="Percent"
  30. width="100" height="100"
  31. anchorPointX="0.5" anchorPointY="0.5" ignoreAnchorPoint="true"
  32. scaleX="1" scaleY="1"
  33. >
  34. <Sprite positionType="LeftBottom" width="720.0" height="1280.0" positionX="0" positionY="0" anchorPointX="0"
  35. anchorPointY="0" src="Resources/bg.png" name="" var="" target="None" scaleX="1" scaleY="1" visible="true"/>
  36. <LayerColor positionType="LeftBottom" width="720" height="1280" positionX="0" positionY="0" anchorPointX="0"
  37. anchorPointY="0" color="#fff2e8ff" visible="false"/>
  38. <Menu positionType="LeftBottom" width="40" height="40" positionX="356.0" positionY="237.0" anchorPointX="0.5"
  39. anchorPointY="0.5" scaleX="2.4" scaleY="1.725">
  40. </Menu>
  41. <Sprite positionType="LeftBottom" width="840.0" height="281.0" positionX="0" positionY="0" anchorPointX="0"
  42. anchorPointY="0" src="Resources/ground.png" var="ground" target="Doc"/>
  43. <Node positionType="LeftBottom" width="40" height="40" positionX="800" positionY="250" anchorPointX="0"
  44. anchorPointY="0" var="hoseNode" target="Doc">
  45. <Sprite positionType="LeftBottom" width="86.0" height="60.0" positionX="-500" positionY="400" anchorPointX="0.5"
  46. anchorPointY="0.5" src="Resources/flappy_packer.plist/bird3.png" var="test" target="Doc" visible="false"/>
  47. <Sprite positionType="LeftBottom" width="86.0" height="60.0" positionX="-550" positionY="500" anchorPointX="0.5"
  48. anchorPointY="0.5" src="Resources/flappy_packer.plist/bird1.png" var="bird" target="Doc" scaleX="1" scaleY="1" rotation="0" visible="true"/>
  49. </Node>
  50. <Node positionType="LeftBottom" width="40" height="40" positionX="303.0" positionY="500" anchorPointX="0.5"
  51. anchorPointY="0.5" var="readyNode" target="Doc" visible="true">
  52. <Sprite positionType="LeftBottom" width="508.0" height="158.0" positionX="95.0" positionY="584.0" anchorPointX="0.5"
  53. anchorPointY="0.5" src="Resources/flappy_packer.plist/getready.png"/>
  54. <Sprite positionType="LeftBottom" width="286.0" height="246.0" positionX="73.0" positionY="236.0" anchorPointX="0.5"
  55. anchorPointY="0.5" src="Resources/flappy_packer.plist/click.png"/>
  56. </Node>
  57. <Node positionType="LeftBottom" width="40" height="40" positionX="300" positionY="500" anchorPointX="0.5"
  58. anchorPointY="0.5" var="overNode" target="Doc" visible="true">
  59. <Sprite positionType="LeftBottom" width="590.0" height="298.0" positionX="72.0" positionY="219.0" anchorPointX="0.5"
  60. anchorPointY="0.5" src="Resources/flappy_packer.plist/base.png">
  61. <Sprite positionType="LeftBottom" width="508.0" height="158.0" positionX="286.0" positionY="458.0" anchorPointX="0.5"
  62. anchorPointY="0.5" src="Resources/flappy_packer.plist/gameover.png"/>
  63. </Sprite>
  64. <Menu positionType="LeftBottom" width="40" height="40" positionX="0" positionY="0" anchorPointX="0.5"
  65. anchorPointY="0.5">
  66. <MenuItem positionType="LeftBottom" width="290" height="176" positionX="-65.0" positionY="-92.0" anchorPointX="0.5"
  67. anchorPointY="0.5" normalImage="Resources/flappy_packer.plist/start.png" target="Doc" onClick="onStartClicked"/>
  68. <MenuItem positionType="LeftBottom" width="290" height="176" positionX="230.0" positionY="-92.0" anchorPointX="0.5"
  69. anchorPointY="0.5" target="Doc" normalImage="Resources/flappy_packer.plist/grade.png" onClick="onGradeClicked"/>
  70. </Menu>
  71. </Node>
  72. </Layer>
  73. </Document>

2 代码编写MainLayer.js

首先,小鸟在向前飞,其实是底部的路和水管在向左移动,相对的你就感觉小鸟在向右飞了;路循环移动代码:

  1. MainLayer.prototype.groundRun = function ()
  2. {
  3. var action1 = cc.MoveTo.create(0.5, cc.p(-120, 0));
  4. var action2 = cc.MoveTo.create(0, cc.p(0, 0));
  5. var action = cc.Sequence.create(action1, action2);
  6. this.ground.runAction(cc.RepeatForever.create(action));
  7. }

初始化高低不同的水管,每一关卡都由上下两水管和空隙组成。总长度相同,空隙也一定,随机取下面水管的长度,就形成错落有致的水管关卡;

  1. MainLayer.prototype.newHose = function (num)
  2. {
  3. var hoseHeight = 830;
  4. var acrossHeight = 300;
  5. var downHeight = 100 + getRandom(400);
  6. var upHeight = 1100 - downHeight - acrossHeight;
  7. var hoseX = 400 * num;
  8. var HoseName = FP_MAIN_TEXTURE.HOSE;
  9. var ccSpriteDown = cc.Sprite.createWithSpriteFrameName(HoseName[0]);
  10. ccSpriteDown.setZOrder(1);
  11. ccSpriteDown.setAnchorPoint(cc.p(0, 0));
  12. ccSpriteDown.setPosition(cc.p(hoseX, 0));
  13. ccSpriteDown.setScaleY(downHeight / hoseHeight);
  14. var ccSpriteUp = cc.Sprite.createWithSpriteFrameName(HoseName[1]);
  15. ccSpriteUp.setZOrder(1);
  16. ccSpriteUp.setAnchorPoint(cc.p(0, 0));
  17. ccSpriteUp.setPosition(cc.p(hoseX, downHeight + acrossHeight));
  18. ccSpriteUp.setScaleY(upHeight / hoseHeight);
  19. this.hoseNode.addChild(ccSpriteDown);
  20. this.hoseNode.addChild(ccSpriteUp);
  21. this.hoseSpriteList.push(ccSpriteDown);
  22. this.hoseSpriteList.push(ccSpriteUp);
  23. return null;
  24. }

一开始进入游戏让底部路不断移动,初始化水管,显示准备游戏场景;

  1. MainLayer.prototype.onEnter = function ()
  2. {
  3. cc.AnimationCache.getInstance().addAnimations("Resources/flappy_frame.plist");
  4. this.groundRun();
  5. this.ground.setZOrder(10);
  6. this.birdReadyAction();
  7. this.bird.setZOrder(20);
  8. this.readyNode.setVisible(true);
  9. this.overNode.setVisible(false);
  10. for (var i = 0; i < 30; i++) {
  11. this.newHose(i);
  12. }
  13. }

点击屏幕,小鸟向上飞60dp,然后更快的速度下落(移动动画),同时闪动翅膀(帧动画);

  1. MainLayer.prototype.birdRiseAction = function ()
  2. {
  3. var riseHeight = 60;
  4. var birdX = this.bird.getPositionX();
  5. var birdY = this.bird.getPositionY();
  6. var time = birdY / 600;
  7. var actionFrame = cc.Animate.create(cc.AnimationCache.getInstance().getAnimation("fly"));
  8. var flyAction = cc.Repeat.create(actionFrame, 90000);
  9. var riseAction1 = cc.MoveTo.create(0.2, cc.p(birdX, birdY + riseHeight));
  10. var riseAction2 = cc.RotateTo.create(0, -30);
  11. var riseAction = cc.Spawn.create(riseAction1, riseAction2);
  12. var fallAction1 = cc.MoveTo.create(time, cc.p(birdX, 50));
  13. var fallAction2 = cc.Sequence.create(cc.DelayTime.create(time / 6), cc.RotateTo.create(0, 30));
  14. var fallAction = cc.Spawn.create(fallAction1, fallAction2);
  15. this.bird.stopAllActions();
  16. this.bird.runAction(cc.Spawn.create(
  17. cc.Sequence.create(riseAction, cc.DelayTime.create(0.1), fallAction),
  18. flyAction)
  19. );
  20. }

检测碰撞,如果小鸟碰到地面和水管,发生碰撞,这里碰撞直接用cocos2d-x 里面的图片和图片交叉函数 cc.rectIntersectsRect;

  1. MainLayer.prototype.checkCollision = function ()
  2. {
  3. if (this.bird.getPositionY() < 60) {
  4. cc.log("floor");
  5. this.birdFallAction();
  6. return;
  7. }
  8. for (var i = 0; i < this.hoseSpriteList.length; i++) {
  9. var hose = this.hoseSpriteList[i];
  10. if (!this.isInScreen(hose)) {
  11. // continue;
  12. }
  13. if (cc.rectIntersectsRect(hose.getBoundingBox(), this.bird.getBoundingBox())) {
  14. cc.log("hose positionX==" + hose.getBoundingBox().x);
  15. cc.log("this.bird positionX==" + this.bird.getBoundingBox().x);
  16. cc.log("i==" + i);
  17. cc.log("birdFallAction");
  18. this.birdFallAction();
  19. return;
  20. }
  21. }
  22. }

碰撞后,小鸟先下落,游戏结束场景显示;

  1. MainLayer.prototype.birdFallAction = function ()
  2. {
  3. this.gameMode = OVER;
  4. this.bird.stopAllActions();
  5. this.ground.stopAllActions();
  6. var birdX = this.bird.getPositionX();
  7. var birdY = this.bird.getPositionY();
  8. var time = birdY / 2000;
  9. this.bird.runAction(cc.Sequence.create(
  10. cc.DelayTime.create(0.1),
  11. cc.Spawn.create(cc.RotateTo.create(time, 90), cc.MoveTo.create(time, cc.p(birdX, 50))))
  12. );
  13. this.overNode.setVisible(true);
  14. }

游戏的难度主要在于多个水管的移动,小鸟触摸动画,检测碰撞,我把Mainlayer.js所有代码贴出来;

  1. FP_MAIN_TEXTURE = {
  2. FRAME_ANIMS: "beanstalk/Resources/bs_main_anims.plist",
  3. HOSE: ["holdback1.png", "holdback2.png"]
  4. }
  5. READY = 1;
  6. START = 2;
  7. OVER = 3;
  8. var MainLayer = function ()
  9. {
  10. cc.log("MainLayer");
  11. this.bird = this.bird || {};
  12. this.ground = this.ground || {};
  13. this.hoseNode = this.hoseNode || {};
  14. this.readyNode = this.readyNode || {};
  15. this.overNode = this.overNode || {};
  16. this.passTime = 0;
  17. this.hoseSpriteList = [];
  18. this.isStart = false;
  19. this.gameMode = READY;
  20. };
  21. MainLayer.prototype.onDidLoadFromCCB = function ()
  22. {
  23. if (sys.platform == 'browser') {
  24. this.onEnter();
  25. }
  26. else {
  27. this.rootNode.onEnter = function ()
  28. {
  29. this.controller.onEnter();
  30. };
  31. }
  32. this.rootNode.schedule(function (dt)
  33. {
  34. this.controller.onUpdate(dt);
  35. });
  36. this.rootNode.onExit = function ()
  37. {
  38. this.controller.onExit();
  39. };
  40. this.rootNode.onTouchesBegan = function (touches, event)
  41. {
  42. this.controller.onTouchesBegan(touches, event);
  43. return true;
  44. };
  45. this.rootNode.onTouchesMoved = function (touches, event)
  46. {
  47. this.controller.onTouchesMoved(touches, event);
  48. return true;
  49. };
  50. this.rootNode.onTouchesEnded = function (touches, event)
  51. {
  52. this.controller.onTouchesEnded(touches, event);
  53. return true;
  54. };
  55. this.rootNode.setTouchEnabled(true);
  56. };
  57. MainLayer.prototype.onEnter = function ()
  58. {
  59. cc.AnimationCache.getInstance().addAnimations("Resources/flappy_frame.plist");
  60. this.groundRun();
  61. this.ground.setZOrder(10);
  62. this.birdReadyAction();
  63. this.bird.setZOrder(20);
  64. this.readyNode.setVisible(true);
  65. this.overNode.setVisible(false);
  66. for (var i = 0; i < 30; i++) {
  67. this.newHose(i);
  68. }
  69. }
  70. MainLayer.prototype.newHose = function (num)
  71. {
  72. var hoseHeight = 830;
  73. var acrossHeight = 300;
  74. var downHeight = 100 + getRandom(400);
  75. var upHeight = 1100 - downHeight - acrossHeight;
  76. var hoseX = 400 * num;
  77. var HoseName = FP_MAIN_TEXTURE.HOSE;
  78. var ccSpriteDown = cc.Sprite.createWithSpriteFrameName(HoseName[0]);
  79. ccSpriteDown.setZOrder(1);
  80. ccSpriteDown.setAnchorPoint(cc.p(0, 0));
  81. ccSpriteDown.setPosition(cc.p(hoseX, 0));
  82. ccSpriteDown.setScaleY(downHeight / hoseHeight);
  83. var ccSpriteUp = cc.Sprite.createWithSpriteFrameName(HoseName[1]);
  84. ccSpriteUp.setZOrder(1);
  85. ccSpriteUp.setAnchorPoint(cc.p(0, 0));
  86. ccSpriteUp.setPosition(cc.p(hoseX, downHeight + acrossHeight));
  87. ccSpriteUp.setScaleY(upHeight / hoseHeight);
  88. this.hoseNode.addChild(ccSpriteDown);
  89. this.hoseNode.addChild(ccSpriteUp);
  90. this.hoseSpriteList.push(ccSpriteDown);
  91. this.hoseSpriteList.push(ccSpriteUp);
  92. return null;
  93. }
  94. MainLayer.prototype.groundRun = function ()
  95. {
  96. var action1 = cc.MoveTo.create(0.5, cc.p(-120, 0));
  97. var action2 = cc.MoveTo.create(0, cc.p(0, 0));
  98. var action = cc.Sequence.create(action1, action2);
  99. this.ground.runAction(cc.RepeatForever.create(action));
  100. }
  101. MainLayer.prototype.birdReadyAction = function ()
  102. {
  103. var birdX = this.bird.getPositionX();
  104. var birdY = this.bird.getPositionY();
  105. var time = birdY / 2000;
  106. var actionFrame = cc.Animate.create(cc.AnimationCache.getInstance().getAnimation("fly"));
  107. var flyAction = cc.Repeat.create(actionFrame, 90000);
  108. this.bird.runAction(cc.Sequence.create(
  109. flyAction)
  110. );
  111. }
  112. MainLayer.prototype.birdFallAction = function ()
  113. {
  114. this.gameMode = OVER;
  115. this.bird.stopAllActions();
  116. this.ground.stopAllActions();
  117. var birdX = this.bird.getPositionX();
  118. var birdY = this.bird.getPositionY();
  119. var time = birdY / 2000;
  120. this.bird.runAction(cc.Sequence.create(
  121. cc.DelayTime.create(0.1),
  122. cc.Spawn.create(cc.RotateTo.create(time, 90), cc.MoveTo.create(time, cc.p(birdX, 50))))
  123. );
  124. this.overNode.setVisible(true);
  125. }
  126. MainLayer.prototype.birdRiseAction = function ()
  127. {
  128. var riseHeight = 60;
  129. var birdX = this.bird.getPositionX();
  130. var birdY = this.bird.getPositionY();
  131. var time = birdY / 600;
  132. var actionFrame = cc.Animate.create(cc.AnimationCache.getInstance().getAnimation("fly"));
  133. var flyAction = cc.Repeat.create(actionFrame, 90000);
  134. var riseAction1 = cc.MoveTo.create(0.2, cc.p(birdX, birdY + riseHeight));
  135. var riseAction2 = cc.RotateTo.create(0, -30);
  136. var riseAction = cc.Spawn.create(riseAction1, riseAction2);
  137. var fallAction1 = cc.MoveTo.create(time, cc.p(birdX, 50));
  138. var fallAction2 = cc.Sequence.create(cc.DelayTime.create(time / 6), cc.RotateTo.create(0, 30));
  139. var fallAction = cc.Spawn.create(fallAction1, fallAction2);
  140. this.bird.stopAllActions();
  141. this.bird.runAction(cc.Spawn.create(
  142. cc.Sequence.create(riseAction, cc.DelayTime.create(0.1), fallAction),
  143. flyAction)
  144. );
  145. }
  146. MainLayer.prototype.onUpdate = function (dt)
  147. {
  148. if (this.gameMode != START) {
  149. return;
  150. }
  151. this.passTime += dt;
  152. this.hoseNode.setPositionX(800 - 200 * this.passTime);
  153. this.bird.setPositionX(-500 + 200 * this.passTime);
  154. this.checkCollision();
  155. }
  156. MainLayer.prototype.checkCollision = function ()
  157. {
  158. if (this.bird.getPositionY() < 60) {
  159. cc.log("floor");
  160. this.birdFallAction();
  161. return;
  162. }
  163. for (var i = 0; i < this.hoseSpriteList.length; i++) {
  164. var hose = this.hoseSpriteList[i];
  165. if (!this.isInScreen(hose)) {
  166. // continue;
  167. }
  168. if (cc.rectIntersectsRect(hose.getBoundingBox(), this.bird.getBoundingBox())) {
  169. cc.log("hose positionX==" + hose.getBoundingBox().x);
  170. cc.log("this.bird positionX==" + this.bird.getBoundingBox().x);
  171. cc.log("i==" + i);
  172. cc.log("birdFallAction");
  173. this.birdFallAction();
  174. return;
  175. }
  176. }
  177. }
  178. MainLayer.prototype.isInScreen = function (sprite)
  179. {
  180. return (sprite.getPositionX() > 0 && sprite.getPositionX() < 720);
  181. }
  182. MainLayer.prototype.onExitClicked = function ()
  183. {
  184. }
  185. MainLayer.prototype.onStartClicked = function ()
  186. {
  187. cc.Director.getInstance().resume();
  188. cc.BuilderReader.runScene("", "MainLayer");
  189. }
  190. MainLayer.prototype.onExit = function ()
  191. {
  192. cc.log("onExit");
  193. }
  194. MainLayer.prototype.onTouchesBegan = function (touches, event)
  195. {
  196. var loc = touches[0].getLocation();
  197. }
  198. MainLayer.prototype.onTouchesMoved = function (touches, event)
  199. {
  200. }
  201. MainLayer.prototype.onTouchesEnded = function (touches, event)
  202. {
  203. if (this.gameMode == OVER) {
  204. return;
  205. }
  206. if (this.gameMode == READY) {
  207. this.gameMode = START;
  208. this.readyNode.setVisible(false);
  209. }
  210. var loc = touches[0].getLocation();
  211. this.birdRiseAction();
  212. }
  213. function isInRect(ccRect, ccTouchBeganPos)
  214. {
  215. if (ccTouchBeganPos.x > ccRect.x && ccTouchBeganPos.x < (ccRect.x + ccRect.width)) {
  216. if (ccTouchBeganPos.y > ccRect.y && ccTouchBeganPos.y < (ccRect.y + ccRect.height)) {
  217. return true;
  218. }
  219. }
  220. return false;
  221. }
  222. function getRandom(maxSize)
  223. {
  224. return Math.floor(Math.random() * maxSize) % maxSize;
  225. }

再次提示代码下载地址:

csdn下载:http://download.csdn.net/detail/touchsnow/6912707

百度云盘:http://pan.baidu.com/s/1pJnWDb9

金山快盘 :http://www.kuaipan.cn/file/id_25348935635745384.htm?source=1

flappy博文系列:

flappy bird游戏源代码揭秘和下载

flappy bird游戏源代码揭秘和下载后续---移植到android真机上

flappy bird游戏源代码揭秘和下载后续---移植到html5网页浏览器

flappy bird游戏源代码揭秘和下载后续---日进5万美元的秘诀AdMob广告

flappy bird游戏源代码揭秘和下载后续---移植到苹果ios上 (未写)

笔者语:

想了解更多请进入官方博客,最新博客和代码在官方博客首发;请持续关注,还有更多cocos2dx editor游戏源码即将放出;

联系笔者:zuowen@makeapp.co(邮箱)qq群:232361142

后言:

为了鼓励更多手游爱好者加入cocos2d-x editor阵营,也为了读者坚定对该工具的信心,笔者基于以上的flappy bird代码和新的图片资源,往google play和中国应用市场发布了一个相似的游戏----腾飞的小鸟(fly bird)。该游戏还加入了广告模块,可以获得些许的广告费。也希望读者通过cocos2d-x editor可以在市场上发布更多的好游戏;

google play地址:https://play.google.com/store/apps/details?id=com.makeapp.game.flybird (小秘密:如果应用.apk后缀改为.rar,你会获得意想不到的东西

豌豆荚市场地址:http://www.wandoujia.com/apps/com.makeapp.game.flybird

机锋市场地址:    http://apk.gfan.com/Product/App741996.html

html5在线演示:http://www.makeapp.co/flybird/ (微软ie浏览器存在兼容性问题,请选择其他浏览器;公司内网,小卡,见谅)

上一篇:PHP 抓取函数curl 实践


下一篇:jQuery的delegate()与proxy()方法