可能网上早就有几个flappy-bird的html5版本啦,到这个时候flappy-bird可能也没有之前那么火了,但是作为一个新手,自己思考,自己动手写一个flappy-bird的demo还是很有成就感的。

flappy-bird的html5版无非是通过canvas来画的,可能网上也有webgl版本的,但是我貌似没见过,如果你发现了,希望告诉我一声,咱们一起讨论讨论。之前在微博上看到有大神用60几行就写出了一个demo,这让我写完之后发现自己的demo有将近200多行的代码,瞬间让我对大神们膜拜的五体投地,当然我的代码也可以精简到几十行,不过那样写出来,不便于维护,对于新人也很难看懂。

html代码我就不写了,大家也都知道,如果你连html代码也需要的话,那你接下来也就没必要看了,还不如直接跳转到w3school.com.cn。

接下来就是重点的js了,至于css吗?你知道的css对于canvas是无效的,那我干嘛还写css呢,这不是浪费生命吗

一开始先是定义bird对象,建议用构造函数的方法,当然你也可以用工厂函数,这没什么关系的

  1. var Bird = function (param) {
  2. this.x = param.x || 0;
  3. this.y = param.y || 0;
  4. this.w = param.w;
  5. this.h = param.h;
  6. this.yDir = param.yDir || 1;
  7. this.img = param.img;
  8. return this;
  9. }

创建一个bird的构造函数,传入参数param 并返回this,参数param是相关的配置参数。

接下来是bird的draw属性,这个属性主要是将bird给画出来

  1. Bird.prototype.draw = function () {
  2. ctx.drawImage(this.img, 0, 0, this.img.width, this.img.height, this.x, this.y, this.w, this.h);
  3. return this;
  4. };

ok,就这么简单,只是简单的调用canvas的drawImage方法

接下来就是bird的jump属性,这个属性主要是控制bird的下滑,模仿小鸟的下降

  1. Bird.prototype.jump = function () {
  2. this.y += this.yDir;
  3. this.draw();
  4. return this;
  5. }

没错,还是这么简单,就是修改y参数,然后调用draw方法,额,其实jump方法和draw方法是可以合并的,不过为了以后的扩展或者,修改方便,我还是选择分开了。当然若是合并了,我的代码又可以少几行了。

上面就完成了bird对象的定义,没错,已经完成了,就一点代码而已。没有太多

接下来是水管对象的定义,不过我人太懒,实在是不想找水管的那个图片,所以我就偷工减料,用了几个盒子来代替水管,原理是一样的,但是视觉效果,你懂的,就比如我身边的一个女性同学说的,程序猿能有什么美感!大家将就着吧

定义盒子对象

  1. var Box = function (x, y) {
  2. this.x = x || boxOption.x;
  3. this.y = y || boxOption.y;
  4. this.w = boxOption.w;
  5. this.h = boxOption.h;
  6. this.img = boxOption.img;
  7. this.visible = true;
  8. return this;
  9. };

是不是觉得和bird很像,不过就是多了visible属性,这个属性是控制盒子的看见与否,在游戏中的小鸟通过的的水管之间的空隙就是靠它了,

还是要定义它几个方法,不对,它只有一个方法

  1. Box.prototype.draw = function () {
  2. // console.log([this.img, this.img.width, this.img.height, this.x, this.y, this.w, this.h]);
  3. ctx.drawImage(this.img, 0, 0, this.img.width, this.img.height, this.x, this.y,
  4. this.w, this.h);
  5. };

有没有觉得这个方法和bird的draw方法一样,没错是一样的,其实我应该让box继承bird对象,这样我的代码有可以少几行了

好了,不谈代码行数的问题了,伤心

接下来是pipe的对象,它不过是box的一个集合

  1. var pipe = function (posX, xDir, maxNum) {
  2. this.x = posX;
  3. this.xDir = xDir;
  4. var boxList = [];
  5. var box = new Box(0, 0);
  6. var boxW = box.w,
  7. boxH = box.h;
  8. var boxTmp;
  9. var maxNum = maxNum || Math.ceil(canvas.height / boxW);
  10. for (var i = 0; i < maxNum; i++) {
  11. boxTmp = new Box(posX, i * boxH);
  12. boxList.push(boxTmp);
  13. }
  14. this.obj = boxList;
  15. this.boxW = boxW;
  16. return this;
  17. };

this.obj这个属性就是box数组

和前面一样,pipe也有个draw属性

  1. pipe.prototype.draw = function () {
  2. var box;
  3. for (var i = 0; i < this.obj.length; i++) {
  4. box = this.obj[i];
  5. box.x = this.x;
  6. if (box.visible) {
  7. box.draw();
  8. }
  9. }
  10. return this;
  11. };

就是将this.obj中的所有box来一次遍历输出,当然box的visible属性必须是可见的

下面的这个方法是随机隐藏两个连续的box,以便给可伶的小鸟通过,我们是仁慈的,给了两个box的高度,当然如果你要是想虐人的话,建议你只给一个高度

  1. // 随机隐藏两个连续的箱子
  2. pipe.prototype.rand = function () {
  3. for (var i = 0; i < this.obj.length; i++) {
  4. this.obj[i].visible = true;
  5. }
  6. var rand = Math.floor(Math.random() *  5) + 1;
  7. // console.log(rand);
  8. this.obj[rand].visible = false;
  9. this.obj[rand + 1].visible = false;
  10. return this;
  11. };

最后一个属性是移动方法,这是让水管进行左右移动的

  1. pipe.prototype.move = function () {
  2. this.x += this.xDir;
  3. // console.log(this.x, this.xDir, this.boxW);
  4. if (this.x < -this.boxW) {
  5. this.x = canvas.width;
  6. this.rand();
  7. }
  8. this.draw();
  9. return this;
  10. };

ok 基本这样ok了,但是我们是不是忘了什么东西啊,想起来了,我们还没有进行碰撞检测呢,如果不进行碰撞检测,那岂不是开挂了,这当然是不行的

  1. // 碰撞函数
  2. function collision (bird, pipe1) {
  3. var birdx = bird.x,
  4. birdy = bird.y,
  5. birdw = bird.w,
  6. birdh = bird.h;
  7. var boxes = pipe1.obj;
  8. var box1, box2, num;
  9. for (var i = 0; i < boxes.length - 1; i++) {
  10. // 找到被隐藏的两个盒子
  11. if (!boxes[i].visible) {
  12. box1 = boxes[i];
  13. box2 = boxes[i + 1];
  14. break;
  15. }
  16. }
  17. var emptyx = box1.x;
  18. var emptyy = box1.y;
  19. var emptyw = box1.w;
  20. var emptyh = box1.h + box2.h;
  21. // 检测是否与上半部水管碰撞
  22. console.log([birdx, birdy, birdw, birdh, emptyx, 0, emptyw, box1.y, boxes[0].y]);
  23. var collUp = calculate(birdx, birdy, birdw, birdh, emptyx, 0, emptyw, box1.y);
  24. // 检测是否与下半部水管碰撞
  25. var collDown = calculate(birdx, birdy, birdw, birdh, emptyx, box2.y + box2.h, emptyw, canvas.height - box2.y - box2.h);
  26. // console.log(collUp, collDown);
  27. if (collUp || collDown) {
  28. // alert('game over');
  29. console.log('game over 1111');
  30. console.log(myReq);
  31. stop();
  32. }
  33. if (birdy > canvas.height - birdh) {
  34. console.log('game over   222');
  35. console.log(myReq);
  36. stop();
  37. }
  38. }
  39. // 计算碰撞函数,默认矩形碰撞
  40. function calculate (x1, y1, w1, h1, x2, y2, w2, h2) {
  41. var ax = x1 + w1 / 2,
  42. ay = y1 + h1 / 2,
  43. bx = x2 + w2 / 2,
  44. by = y2 + h2 / 2;
  45. var collX = false, collY = false;
  46. (Math.abs(bx - ax) < (w1 + w2) / 2) && (collX = true);
  47. (Math.abs(by - ay) < (h1 + h2) / 2) && (collY = true);
  48. return collX && collY;
  49. }

这样就基本ok了,接下来也只是一些,初始化而已,这个直接上代码吧

  1. var count = 0, timeout, myReq = 0, stopped, requestId = 0;
  2. function render() {
  3. if (!stopped) {
  4. ctx.fillStyle = '#ccc';
  5. ctx.fillRect(0, 0, canvas.width, canvas.height);
  6. bird.jump();
  7. pipe1.move();
  8. // 检测碰撞
  9. collision(bird, pipe1);
  10. requestId = window.requestAnimationFrame(render);
  11. console.log(requestId);
  12. }
  13. }
  14. // 绑定鼠标事件
  15. document.onclick = function () {
  16. bird.y -= 25;
  17. }
  18. function start() {
  19. requestId = window.requestAnimationFrame(render);
  20. stopped = false;
  21. // console.log(requestId);
  22. }
  23. function stop() {
  24. if (requestId) {
  25. window.cancelAnimationFrame(requestId);
  26. }
  27. stopped = true;
  28. // console.log(requestId);
  29. }
  30. start();

效果如下图所示

完整代码请访问我的github

https://github.com/chenkehxx/mytest/blob/master/flappy-bird/flappy-bird.html

用html5实现的flappy-bird的更多相关文章

  1. 【教程】HTML5+JavaScript编写flappy bird

         作者: 风小锐      新浪微博ID:永远de风小锐      QQ:547953539      转载请注明出处 PS:新修复了两个bug,已下载代码的同学请查看一下 大学立即要毕业了. ...

  2. HTML5 版的flappy bird

    Flappy Bird这款简单的小游戏累计下载量已经超过5000万次,每天收入至少5万美元.然而,2月10日其开发者Dong Nguyen却将Flappy Bird从苹果App Store和Googl ...

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

    转:http://blog.csdn.net/touchsnow/article/details/19071961 背景: 最近火爆全球的游戏flappy bird让笔者叹为观止,于是花了一天的时间山 ...

  4. 使用Hilo.JS快速开发Flappy Bird

    http://hiloteam.github.io/tutorial/flappybird.html#_9 Flappy Bird是一款前不久风靡世界的休闲小游戏.虽然它难度超高,但是游戏本身却非常简 ...

  5. 闲扯游戏编程之html5篇--山寨版《flappy bird》源码

    新年新气象,最近事情不多,继续闲暇学习记点随笔,欢迎拍砖.之前的〈简单游戏学编程语言python篇〉写的比较幼稚和粗糙,且告一段落.开启新的一篇关于javascript+html5的从零开始的学习.仍 ...

  6. 用Phaser来制作一个html5游戏——flappy bird (二)

    在上一篇教程中我们完成了boot.preload.menu这三个state的制作,下面我们就要进入本游戏最核心的一个state的制作了.play这个state的代码比较多,我不会一一进行说明,只会把一 ...

  7. 用Phaser来制作一个html5游戏——flappy bird (一)

    Phaser是一个简单易用且功能强大的html5游戏框架,利用它可以很轻松的开发出一个html5游戏.在这篇文章中我就教大家如何用Phaser来制作一个前段时间很火爆的游戏:Flappy Bird,希 ...

  8. 通通制作Html5小游戏——第二弹(仿flappy bird像素鸟)

    亲爱的博友们,我又回来啦~因为我们技术宅的思想只有技术宅懂得,好不容易写了点好玩的东西发QQ空间,结果只有11的UV,0回复....10分钟ps一个女神的素描效果发QQ空间朋友圈,一大堆回复加赞,作为 ...

  9. 65行 JavaScript 代码实现 Flappy Bird 游戏

    飞扬的小鸟(Flappy Bird)无疑是2014年全世界最受关注的一款游戏.这款游戏是一位来自越南河内的独立游戏开发者阮哈东开发,形式简易但难度极高的休闲游戏,很容易让人上瘾. 这里给大家分享一篇这 ...

  10. 用Phaser实现Flappy Bird 游戏

    How to Make a Flappy Bird in HTML5 With Phaser - Part 1 Flappy Bird is a nice little game with easy ...

随机推荐

  1. c++ 前置++与后置++的区别

    用C++编程的都知道,C++提供了一个非常强大的操作符重载机制,利用操作符重载,我们可以为我们自定义的类增加更多非常有用的功能.不过,C++也有限制,就是当我们为自定义的类重载操作符时,重载操作符的含 ...

  2. highCharts参数实例解释

    <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content ...

  3. php设计模式之六大设计原则

      1.单一职责 定义:不要存在多于一个导致类变更的原因.通俗的说,即一个类只负责一项职责. 场景:类T负责两个不同的职责:职责P1,职责P2.当由于职责P1需求发生改变而需要修改类T时,有可能会导致 ...

  4. Spring Enable*高级应用及原理

    Enable* 之前的文章用到了一些Enable*开头的注解,比如EnableAsync.EnableScheduling.EnableAspectJAutoProxy.EnableCaching等, ...

  5. 凸优化(Convex Optimization)浅析

    本博客已经迁往http://www.kemaswill.com/, 博客园这边也会继续更新, 欢迎关注~ 在机器学习中, 很多情况下我们都需要求得一个 问题的全局最优值(global optimum) ...

  6. fifo 上使用 select -- 转

    http://www.outflux.net/blog/archives/2008/03/09/using-select-on-a-fifo/ The right way to handle on-g ...

  7. [NOIP2015提高&洛谷P2678]跳石头 题解(二分答案)

    [NOIP2015提高&洛谷P2678]跳石头 Description 这项比赛将在一条笔直的河道中进行,河道中分布着一些巨大岩石.组委会已经选择好了两块岩石作为比赛起点和终点.在起点和终点之 ...

  8. REX系统了解1

    REX是高通开发出来的一个操作系统,起初它是为了在Inter 80186处理器上应用而开发的,到后来才转变成应用在ARM这种微处理器上.他历经了很多版本,代码也越来越多,功能也越来越完善.REX只用不 ...

  9. linux shell语言编程规范安全篇之通用原则【转】

    shell语言编程规范安全篇是针对bash语言编程中的数据校验.加密与解密.脚本执行.目录&文件操作等方面,描述可能导致安全漏洞或风险的常见编码错误.该规范基于业界最佳实践,并总结了公司内部的 ...

  10. poj1077

    题意:给出一个八数码问题,求解法,不可解则输出unsolvable. 分析:可以用ida*算法,估价函数可以使用每个数码到其最终位置的最短距离之和.对于不可解的判断,我这里用迭代深度大于100时判定为 ...