像素小鸟,Canvas前端游戏支付

[Canvas前端游戏开发]——FlappyBird详解

2016/01/03 · HTML5 ·
Canvas

原稿出处: xingoo   

直接想本人做点小东西,直到近来看了本《HTML5戏耍开发》,才打听游戏开发中的一小点入门知识。

本篇就针对学习的多少个样例,本人入手实践,做了个FlappyBird,源码共享在度盘 ;也足以参考github,里面有更多的7日游样例。

canvas 制作flappy bird(像素小鸟)全流程,canvasflappy

想必网上早就有多少个flappy-bird的html5版本啦,到这么些时候flappy-bird恐怕也从不事先那么火了,可是作为多个新手,自个儿想想,本人出手写多个flappy-bird的demo照旧很有成就感的。

canvas是一个方可让大家运用脚本绘图的竹签,它提供了一层层完整的属性和方法。大家得以借此来促成图形绘制,图像处理依然实现简单的动画片和游玩制作。

游戏截图

皇家赌场手机版 1

皇家赌场手机版 2

flappy bird制作全流程:

皇家赌场手机版 3

flappy-bird的html5版无非是通过canvas来画的,或许网上也有webgl版本的,不过自个儿一般没见过,如若您意识了,希望告知笔者一声,我们一起切磋斟酌。在此之前在乐乎上看出有大神用60几行就写出了二个demo,那让小编写完今后发现自个儿的demo有将近200多行的代码,须臾间让本身对大神们三跪九叩的敬佩,当然作者的代码也能够不难到几十行,不过如此写出来,不便于维护,对于新人也极难看懂。

canvas标签唯有五个本性:width和height,用来设定画布的宽和高,假诺没有通过标签属性恐怕脚本来设置,暗中认可为300*150;

HTML5之Canvas

Canvas是Html5中用于绘图的要素,它能够绘制各个图片,比如椭圆形,多边形,圆形等等。如果想要掌握Canvas的运用可以参考:

 

//要是想要使用canvas,首先须求得到上下文对象: ctx =
document.getElementById(‘canvas’).getContext(‘2d’);
//然后使用这几个ctx绘制图形

1
2
3
//如果想要使用canvas,首先需要获得上下文对象:
ctx = document.getElementById(‘canvas’).getContext(‘2d’);
//然后使用这个ctx绘制图形

在cavas各个绘制都以单独的操作。比如下图的三个绘制图形,第3个会以覆盖的样式绘制,由此制图图形的各种就体现十三分至关心重视要了。

皇家赌场手机版 4

一、前言

像素小鸟这么些大致的游乐于2016年在网络上爆红,游戏上线一段时间内appleStore上的下载量一度高达陆仟万次,风靡一时半刻,

近年移动web的普及为那样没有复杂逻辑和小巧动画效果,可是趣味十足的小游戏提供了要得的条件,

并且借助各大社交软件平台的传播效应,创新意识不断的小游戏有着得天独厚的经营销售效益,获得了累累的关注。

原先在网上查询了过多关于这几个小游戏的资料,可是基本上非常不佳,本身的重组相关课程将以此娱乐的机要框架整理出来,供大家一起上学。

html代码笔者就不写了,大家也都晓得,假诺你连html代码也供给的话,那您接下去也就没须求看了,还不如间接跳转到w3school.com.cn。

好了,canvas的牵线就先到此地,下边咱们来看看javascript结合canvas完结图片的剪裁代码:

canvas之drawImage()

像素小鸟,Canvas前端游戏支付。本篇的游玩支付中,首要选取的是依照图片绘制的api:drawImage(),它有四个着力的利用办法:

ctx.drawImage(image,this.bx,this.by,this.bwidth,this.bheight);
ctx.drawImage(image,x,y,width,height,this.px,this.py,this.pwidth,this.pheight);

1
2
ctx.drawImage(image,this.bx,this.by,this.bwidth,this.bheight);
ctx.drawImage(image,x,y,width,height,this.px,this.py,this.pwidth,this.pheight);

第三个api中,钦赐Image对象,然后给出绘制图片的x,y坐标以及宽度和中度即可。

第一个api中,第1组x,y,width,height则钦点了裁剪图片的坐标尺寸,这在使用多成分的矢量图时很常用。比如:

皇家赌场手机版 5

地方的图片中为了裁减图片能源的乞求数量,把广大的成分放在了三个图纸中,此时就必要经过裁剪的点子,获取钦命的图片成分。

二 、技术核心

 基本JavaScript基础 ,canvas 基础, 面向对象的思索;

接下去就是重点的js了,至于css吗?你理解的css对于canvas是行不通的,那作者干嘛还写css呢,那不是浪费生命啊

复制代码 代码如下:

FlappyBird原理分析

事实上那一个娱乐非常粗略,一张图就能够看懂个中的微妙:

皇家赌场手机版 6

当中背景和本地是不动的。

鸟类唯有上和下五个动作,能够因此决定小鸟的y坐标实现。

前后的管敬仲只会向左移动,为了容易达成,游戏中三个画面仅仅会并发局地管敬仲,那样当管敬仲移出左侧的背景框,就自行把管仲放在最左边!

if(up_pipe.px+up_pipe.pwidth>0){ up_pipe.px -= velocity;
down_pipe.px -= velocity; }else{ up_pipe.px = 400; down_pipe.px =
400; up_pipe.pheight = 100+Math.random()*200; down_pipe.py =
up_pipe.pheight+pipe_height; down_pipe.pheight = 600-down_pipe.py;
isScore = true; }

1
2
3
4
5
6
7
8
9
10
11
if(up_pipe.px+up_pipe.pwidth>0){
                up_pipe.px -= velocity;
                down_pipe.px -= velocity;
            }else{
                up_pipe.px = 400;
                down_pipe.px = 400;
                up_pipe.pheight = 100+Math.random()*200;
                down_pipe.py = up_pipe.pheight+pipe_height;
                down_pipe.pheight = 600-down_pipe.py;
                isScore = true;
            }

相当粗略吗!

由于该游戏一共就那多少个成分,由此把他们都放入一个Objects数组中,通过setInteral()方法,在早晚间隔时间内,执行一次重绘

重绘的时候会先去掉画面中的全部因素,然后根据新的因素的坐标二回绘制图形,那样就会现出活动的效果。

③ 、思路整理

一起始率先定义bird对象,提出用构造函数的方法,当然你也得以用工厂函数,那没怎么关联的

var selectObj = null;
function ImageCrop(canvasId, imageSource, x, y, width, height) {
    var canvas = $(“#” + canvasId);
    if (canvas.length == 0 && imageSource) {
        return;
    }
    function canvasMouseDown(e) {
        StopSelect(e);
        canvas.css(“cursor”, “default”);
    }
    function canvasMouseMove(e) {
        var canvasOffset = canvas.offset();
        var pageX = e.pageX || event.targetTouches[0].pageX;
        var pageY = e.pageY || event.targetTouches[0].pageY;
        iMouseX = Math.floor(pageX – canvasOffset.left);
        iMouseY = Math.floor(pageY – canvasOffset.top);
        canvas.css(“cursor”, “default”);
        if (selectObj.bDragAll) {
            canvas.css(“cursor”, “move”);
            canvas.data(“drag”, true);
            var cx = iMouseX – selectObj.px;
            cx = cx < 0 ? 0 : cx;
            mx = ctx.canvas.width – selectObj.w;
            cx = cx > mx ? mx : cx;
            selectObj.x = cx;
            var cy = iMouseY – selectObj.py;
            cy = cy < 0 ? 0 : cy;
            my = ctx.canvas.height – selectObj.h;
            cy = cy > my ? my : cy;
            selectObj.y = cy;
        }
        for (var i = 0; i < 4; i++) {
            selectObj.bHow[i] = false;
            selectObj.iCSize[i] = selectObj.csize;
        }
        // hovering over resize cubes
        if (iMouseX > selectObj.x – selectObj.csizeh && iMouseX <
selectObj.x + selectObj.csizeh &&
            iMouseY > selectObj.y – selectObj.csizeh && iMouseY <
selectObj.y + selectObj.csizeh) {
            canvas.css(“cursor”, “pointer”);
            selectObj.bHow[0] = true;
            selectObj.iCSize[0] = selectObj.csizeh;
        }
        if (iMouseX > selectObj.x + selectObj.w – selectObj.csizeh &&
iMouseX < selectObj.x + selectObj.w + selectObj.csizeh &&
            iMouseY > selectObj.y – selectObj.csizeh && iMouseY <
selectObj.y + selectObj.csizeh) {
            canvas.css(“cursor”, “pointer”);
            selectObj.bHow[1] = true;
            selectObj.iCSize[1] = selectObj.csizeh;
        }
        if (iMouseX > selectObj.x + selectObj.w – selectObj.csizeh &&
iMouseX < selectObj.x + selectObj.w + selectObj.csizeh &&
            iMouseY > selectObj.y + selectObj.h – selectObj.csizeh &&
iMouseY < selectObj.y + selectObj.h + selectObj.csizeh) {
            canvas.css(“cursor”, “pointer”);
            selectObj.bHow[2] = true;
            selectObj.iCSize[2] = selectObj.csizeh;
        }
        if (iMouseX > selectObj.x – selectObj.csizeh && iMouseX <
selectObj.x + selectObj.csizeh &&
            iMouseY > selectObj.y + selectObj.h – selectObj.csizeh &&
iMouseY < selectObj.y + selectObj.h + selectObj.csizeh) {
            canvas.css(“cursor”, “pointer”);
            selectObj.bHow[3] = true;
            selectObj.iCSize[3] = selectObj.csizeh;
        }
        if (iMouseX > selectObj.x && iMouseX < selectObj.x +
selectObj.w && iMouseY > selectObj.y && iMouseY < selectObj.y +
selectObj.h) {
            canvas.css(“cursor”, “move”);
        }
        // in case of dragging of resize cubes
        var iFW, iFH, iFX, iFY, mx, my;
        if (selectObj.bDrag[0]) {
            iFX = iMouseX – selectObj.px;
            iFY = iMouseY – selectObj.py;
            iFW = selectObj.w + selectObj.x – iFX;
            iFH = selectObj.h + selectObj.y – iFY;
            canvas.data(“drag”, true);
        }
        if (selectObj.bDrag[1]像素小鸟,Canvas前端游戏支付。) {
            iFX = selectObj.x;
            iFY = iMouseY – selectObj.py;
            iFW = iMouseX – selectObj.px – iFX;
            iFH = selectObj.h + selectObj.y – iFY;
            canvas.data(“drag”, true);
        }
        if (selectObj.bDrag[2]) {
            iFX = selectObj.x;
            iFY = selectObj.y;
            iFW = iMouseX – selectObj.px – iFX;
            iFH = iMouseY – selectObj.py – iFY;
            canvas.data(“drag”, true);
        }
        if (selectObj.bDrag[3]) {
            iFX = iMouseX – selectObj.px;
            iFY = selectObj.y;
            iFW = selectObj.w + selectObj.x – iFX;
            iFH = iMouseY – selectObj.py – iFY;
            canvas.data(“drag”, true);
        }
        if (iFW > selectObj.csizeh * 2 && iFH > selectObj.csizeh
* 2) {
            selectObj.w = iFW;
            selectObj.h = iFH;
            selectObj.x = iFX;
            selectObj.y = iFY;
        }
        drawScene();
    }
    function canvasMouseOut() {
        $(canvas).trigger(“mouseup”);
    }
    function canvasMouseUp() {
        selectObj.bDragAll = false;
        for (var i = 0; i < 4; i++) {
            selectObj.bDrag[i] = false;
        }
        canvas.css(“cursor”, “default”);
        canvas.data(“select”, {
            x: selectObj.x,
            y: selectObj.y,
            w: selectObj.w,
            h: selectObj.h
        });
        selectObj.px = 0;
        selectObj.py = 0;
    }
    function Selection(x, y, w, h) {
        this.x = x; // initial positions
        this.y = y;
        this.w = w; // and size
        this.h = h;
        this.px = x; // extra variables to dragging calculations
        this.py = y;
        this.csize = 4; // resize cubes size
        this.csizeh = 6; // resize cubes size (on hover)
        this.bHow = [false, false, false, false]; // hover statuses
        this.iCSize = [this.csize, this.csize, this.csize,
this.csize]; // resize cubes sizes
        this.bDrag = [false, false, false, false]; // drag statuses
        this.bDragAll = false; // drag whole selection
    }
    Selection.prototype.draw = function () {
        ctx.strokeStyle = ‘#666’;
        ctx.lineWidth = 2;
        ctx.strokeRect(this.x, this.y, this.w, this.h);
        // draw part of original image
        if (this.w > 0 && this.h > 0) {
            ctx.drawImage(image, this.x, this.y, this.w, this.h, this.x,
this.y, this.w, this.h);
        }
        // draw resize cubes
        ctx.fillStyle = ‘#999’;
        ctx.fillRect(this.x – this.iCSize[0], this.y –
this.iCSize[0], this.iCSize[0] * 2, this.iCSize[0] * 2);
        ctx.fillRect(this.x + this.w – this.iCSize[1], this.y –
this.iCSize[1], this.iCSize[1] * 2, this.iCSize[1] * 2);
        ctx.fillRect(this.x + this.w – this.iCSize[2], this.y + this.h

萧规曹随小鸟重力

由于这一个娱乐不关乎小鸟横向的移动,由此倘若模拟出小鸟降低的动作以及回涨的动作就足以了。

皇家赌场手机版 7

上升:这些异常粗略,只要把小鸟的y坐标减去肯定的值就足以了

下落:其实重力不须求利用gt^2来效仿,能够省略的钦命七个变量,v1和gravity,那七个变量与setInterval()中的时间一起成效,就能模拟重力。

ver2 = ver1+gravity; bird.by += (ver2+ver1)*0.5;

1
2
ver2 = ver1+gravity;
bird.by += (ver2+ver1)*0.5;

全方位游戏的逻辑相比简单:

率先游戏规则:鸟撞到管道上,地上要回老家,飞到显示器外要离世。

协理:鸟在飞翔的进程中,会落下,类似落体运动,要求玩家不断点击显示器让鸟向上海飞机创制厂。

重复正是:鸟和背景成分的绝对移动的经过,鸟不动,背景左移。

  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.   
  9.                 return this;  
  10.             }  
  • this.iCSize[2], this.iCSize[2] * 2, this.iCSize[2] * 2);
            ctx.fillRect(this.x – this.iCSize[3], this.y + this.h –
    this.iCSize[3], this.iCSize[3] * 2, this.iCSize[3] * 2);
        };
        var drawScene = function () {
            ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height); //
    clear canvas
            // draw source image
            ctx.drawImage(image, 0, 0, ctx.canvas.width,
    ctx.canvas.height);
            // and make it darker
            ctx.fillStyle = ‘rgba(0, 0, 0, 0.5)’;
            ctx.fillRect(0, 0, ctx.canvas.width, ctx.canvas.height);
            // draw selection
            selectObj.draw();
            canvas.mousedown(canvasMouseDown);
            canvas.on(“touchstart”, canvasMouseDown);
        };
        var createSelection = function (x, y, width, height) {
            var content = $(“#imagePreview”);
            x = x || Math.ceil((content.width() – width) / 2);
            y = y || Math.ceil((content.height() – height) / 2);
            return new Selection(x, y, width, height);
        };
        var ctx = canvas[0].getContext(“2d”);
        var iMouseX = 1;
        var iMouseY = 1;
        var image = new Image();
        image.onload = function () {
            selectObj = createSelection(x, y, width, height);
            canvas.data(“select”, {
                x: selectObj.x,
                y: selectObj.y,
                w: selectObj.w,
                h: selectObj.h
            });
            drawScene();
        };
        image.src = imageSource;
        canvas.mousemove(canvasMouseMove);
        canvas.on(“touchmove”, canvasMouseMove);
        var StopSelect = function (e) {
            var canvasOffset = $(canvas).offset();
            var pageX = e.pageX || event.targetTouches[0].pageX;
            var pageY = e.pageY || event.targetTouches[0].pageY;
            iMouseX = Math.floor(pageX – canvasOffset.left);
            iMouseY = Math.floor(pageY – canvasOffset.top);
            selectObj.px = iMouseX – selectObj.x;
            selectObj.py = iMouseY – selectObj.y;
            if (selectObj.bHow[0]) {
                selectObj.px = iMouseX – selectObj.x;
                selectObj.py = iMouseY – selectObj.y;
            }
            if (selectObj.bHow[1]) {
                selectObj.px = iMouseX – selectObj.x – selectObj.w;
                selectObj.py = iMouseY – selectObj.y;
            }
            if (selectObj.bHow[2]) {
                selectObj.px = iMouseX – selectObj.x – selectObj.w;
                selectObj.py = iMouseY – selectObj.y – selectObj.h;
            }
            if (selectObj.bHow[3]) {
                selectObj.px = iMouseX – selectObj.x;
                selectObj.py = iMouseY – selectObj.y – selectObj.h;
            }
            if (iMouseX > selectObj.x + selectObj.csizeh &&
                iMouseX < selectObj.x + selectObj.w – selectObj.csizeh
    &&
                iMouseY > selectObj.y + selectObj.csizeh &&
                iMouseY < selectObj.y + selectObj.h – selectObj.csizeh)
    {
                selectObj.bDragAll = true;
            }
            for (var i = 0; i < 4; i++) {
                if (selectObj.bHow[i]) {
                    selectObj.bDrag[i] = true;
                }
            }
        };
        canvas.mouseout(canvasMouseOut);
        canvas.mouseup(canvasMouseUp);
        canvas.on(“touchend”, canvasMouseUp);
        this.getImageData = function (previewID) {
            var tmpCanvas = $(“<canvas></canvas>”)[0];
            var tmpCtx = tmpCanvas.getContext(“2d”);
            if (tmpCanvas && selectObj) {
                tmpCanvas.width = selectObj.w;
                tmpCanvas.height = selectObj.h;
                tmpCtx.drawImage(image, selectObj.x, selectObj.y,
    selectObj.w, selectObj.h, 0, 0, selectObj.w, selectObj.h);
                if (document.getElementById(previewID)) {
                    document.getElementById(previewID).src =
    tmpCanvas.toDataURL();
                    document.getElementById(previewID).style.border = “1px
    solid #ccc”;
                }
                return tmpCanvas.toDataURL();
            }
        };
    }
    function autoResizeImage(maxWidth, maxHeight, objImg) {
        var img = new Image();
        img.src = objImg.src;
        var hRatio;
        var wRatio;
        var ratio = 1;
        var w = objImg.width;
        var h = objImg.height;
        wRatio = maxWidth / w;
        hRatio = maxHeight / h;
        if (w < maxWidth && h < maxHeight) {
            return;
        }
        if (maxWidth == 0 && maxHeight == 0) {
            ratio = 1;
        } else if (maxWidth == 0) {
            if (hRatio < 1) {
                ratio = hRatio;
            }
        } else if (maxHeight == 0) {
            if (wRatio < 1) {
                ratio = wRatio;
            }
        } else if (wRatio < 1 || hRatio < 1) {
            ratio = (wRatio <= hRatio ? wRatio : hRatio);
        } else {
            ratio = (wRatio <= hRatio ? wRatio : hRatio) –
    Math.floor(wRatio <= hRatio ? wRatio : hRatio);
        }
        if (ratio < 1) {
            if (ratio < 0.5 && w < maxWidth && h < maxHeight) {
                ratio = 1 – ratio;
            }
            w = w * ratio;
            h = h * ratio;
        }
        objImg.height = h;
        objImg.width = w;
    }

碰撞检查和测试

玩耍中型小型鸟蒙受管敬仲也许地方都会算游戏甘休:

皇家赌场手机版 8

其中条件1上管道的检查和测试为:

((bird.bx+bird.bwidth>up_pipe.px)&&(bird.by>up_pipe.py)&&(bird.bx+bird.bwidth<up_pipe.px+up_pipe.pwidth)&&(bird.by<up_pipe.py+up_pipe.pheight))||
((bird.bx+bird.bwidth>up_pipe.px)&&(bird.by>up_pipe.py)&&(bird.bx+bird.bwidth<up_pipe.px+up_pipe.pwidth)&&(bird.by<up_pipe.py+up_pipe.pheight))

1
2
((bird.bx+bird.bwidth>up_pipe.px)&&(bird.by>up_pipe.py)&&(bird.bx+bird.bwidth<up_pipe.px+up_pipe.pwidth)&&(bird.by<up_pipe.py+up_pipe.pheight))||
((bird.bx+bird.bwidth>up_pipe.px)&&(bird.by>up_pipe.py)&&(bird.bx+bird.bwidth<up_pipe.px+up_pipe.pwidth)&&(bird.by<up_pipe.py+up_pipe.pheight))

条件2下管道的检查和测试为:

((bird.bx>down_pipe.px)&&(bird.by>down_pipe.py)&&(bird.bx<down_pipe.px+down_pipe.pwidth)&&(bird.by<down_pipe.py+down_pipe.pheight))||
((bird.bx>down_pipe.px)&&(bird.by+bird.bheight>down_pipe.py)&&(bird.bx<down_pipe.px+down_pipe.pwidth)&&(bird.by+bird.bheight<down_pipe.py+down_pipe.pheight))

1
2
((bird.bx>down_pipe.px)&&(bird.by>down_pipe.py)&&(bird.bx<down_pipe.px+down_pipe.pwidth)&&(bird.by<down_pipe.py+down_pipe.pheight))||
((bird.bx>down_pipe.px)&&(bird.by+bird.bheight>down_pipe.py)&&(bird.bx<down_pipe.px+down_pipe.pwidth)&&(bird.by+bird.bheight<down_pipe.py+down_pipe.pheight))

条件3地面的检测最简单易行,为:

bird.by+bird.bheight>ground.bgy

1
bird.by+bird.bheight>ground.bgy

如若餍足那七个规格,尽管游戏结束,会去掉循环以及提示游戏甘休音信。

将整个娱乐细化:

大家利用面向对象的笔触来创设,具体的东西用构造函数来创制,方法放到构造函数的实质对象中。

娱乐细化那一个历程不是毫不费劲的,假若在没有有关指引的情景下,本人要持续的重组本身的想法去试错。

小编使用的不二法门是使用Xmind将流程以脑图的花样绘制下来,分块去做,不断细化记录本身的思路,最终表现的机能如下:

(顺序依照图片中的序号去看
 脑图、素材、及全部源码下载地址:
想演练的校友能够点那里)

脑图分为三大块:① 、准备阶段 二 、主函数 ③ 、游戏优化。

皇家赌场手机版 9

皇家赌场手机版 10

 

 

创办二个bird的构造函数,传入参数param
并回到this,参数param是有关的布置参数。

伙伴们拿去尝试啊,希望大家能够喜欢,有反常态就给自己留言呢。

分数总括

分数的猜想与碰撞检查和测试类似,设置三个开关,当管敬仲重新出现时,设置为true。当分值加1时,设置为false。

鸟儿的最左侧的x坐标借使超出了管仲的x+width,就以为成功通过。

if(isScore && bird.bx>up_pipe.px+up_pipe.pwidth){ score += 1;
isScore = false; if(score>0 && score%10 === 0){ velocity++; } }

1
2
3
4
5
6
7
if(isScore && bird.bx>up_pipe.px+up_pipe.pwidth){
                score += 1;
                isScore = false;
                if(score>0 && score%10 === 0){
                    velocity++;
                }
            }

通过后,分值加1,速度+1。

 ④ 、游戏实现:

方今重组脑图来稳步落到实处大家的游艺。

1.设置canvas画布,准备图片数据,当图片加载成功后举办回调函数;

皇家赌场手机版 11<canvas
id=”cvs” width=”800″ height=”600″></canvas> <script> var
imglist = [ { “name”:”birds”,”src”:”res/birds.png”}, {
“name”:”land”,”src”:”res/land.png”}, {
“name”:”pipe1″,”src”:”res/pipe1.png”}, {
“name”:”pipe2″,”src”:”res/pipe2.png”}, {
“name”:”sky”,”src”:”res/sky.png”} ]; var cvs =
document.getElementById(“cvs”); var ctx = cvs.getContext(“2d”);
</script> 画布准备
,图片数据准备

此间那一个入口函数的装置要专注,必须保险图片财富加载成功后再实践此外操作,每加载一张图片大家让imgCount–,减到0的时候再履行主函数;

皇家赌场手机版 12function
load (source, callback ){ var imgEls={}; var imgCount=source.length; for
(var i = 0; i < imgCount; i++) { var name = source[i].name; var
newImg = new Image (); newImg.src = source[i].src; imgEls[name] =
newImg; imgEls[name].add伊夫ntListener(“load”,function(){ imgCount–;
if(imgCount==0){ callback(imgEls); }; }) }; }; 入口函数设置

主循环的安装:那里大家不行使setInterval来决定循环次数,大家采纳一个叫requestAnimationFrame()的定时器

       因为setInterval会时有爆发时间误差,setInterval只能依照时间来运动固定距离。

       这对于轮播图一类几千纳秒切换二次的动作来说并不曾什么样关系,不过对于我们16-18皮秒绘制三次的动画是可怜不标准的;

       requestAnimationFrame()这一个定时器的好处是根据浏览器的质量来进行贰个函数,我们用来获得五回绘制的间隔时间;

       移动距离的计算改变成速度×间隔时间的情势,来消除绘图不确切的难题。

皇家赌场手机版 13var
pre提姆e= Date.now(); //获取当后天子 function run(){ var now =
Date.now(); //获取最新时刻 dt = now – preTime; //获取时间距离 preTime =
now; //更新当前岁月 ctx.clearRect(0,0,800,600); //清空画布
//——————————————— 绘制代码执行区域
//———————————————–
requestAnimationFrame(run); //再度执行run函数 }
requestAnimationFrame(run); //首次执行run函数; 设置绘制情势

二 、主函数分为两片段机能
,不难说就是把图画上去,然后处理动态效果,再判断一下是不是违犯禁令。

2.1 小鸟的绘图:

  小鸟自己有贰个翅膀扇动的功用,和2个大跌的长河。

  翅膀扇动的历程是一张天使图三幅画面包车型客车的切换(设置三个index属性,控制天使图的地方),下跌进度是其y坐标在画布上的活动();

  所以小鸟的构造函数中应有包含(图源,x坐标,y坐标,速度,下降加快度,ctx(context画布))等参数。

  那里必要注意几点:

  •  小鸟的绘图选用canvas
    drawImage的九参数形式(分别是图形,原图的裁切源点,原图的宽高,贴到画布上的职责,贴到画布上的宽高);
  •  小鸟的膀子扇动不能太快,所以我们设置二个阀门函数,当累计计时超过100ms的时候切换一下图片,然后在让一起计时减去100ms;
  •  小鸟的骤降供给使用一定物理知识,不过都很简短啦。
    大家都以透过速度×时间来促成;

皇家赌场手机版 14var Bird= function (img,x,y,speed,a,ctx){ this.img = img; this.x = x; this.y =
y; this.speed = speed; this.a =a ; this.ctx = ctx; this.index = 0;
//用于营造小鸟扇翅膀的动作 } 伯德.prototype.draw = function (){
this.ctx.drawImage( this.img,52*this.index,0,52,45, this.x,this.y,52,45
) } var durgather=0; Bird.prototype.update = function(dur){
//小鸟翅膀扇动每100ms切换一张图片 durgather+=dur; if(durgather>100){
this.index++; if(this.index===2){ this.index=0; } durgather -= 100; }
//小鸟下降动作 this.speed = this.speed + this.a *dur; this.y = this.y +
this.speed * dur; } 小鸟的构造函数及动作控制

 
构造一个鸟类,并且将其动作刷新函数和制图函数放置在我们地点提到的绘图区域,此后结构出的好像对象都以这么的操作步骤:

 
那里必要小心的一些是,如何让鸟儿顺畅的上扬飞翔,其实还是物理知识,由于加快度的效果,大家给小鸟两个升华的顺时速度就能够了。

皇家赌场手机版 15load(imglist
,function(imgEls){ //创造对象 //在主函数中创建四个小鸟 var bird = new
Bird(imgEls[“birds”],150,100,0.0003,0.0006,ctx); //主循环 var preTime=
Date.now(); function run(){ var now = Date.now(); dt = now – preTime;
pre提姆e = now; ctx.clearRect(0,0,800,600); //——–图片绘制区域——-
bird.update(dt) bird.draw(); //————————-
requestAnimationFrame(run); } requestAnimationFrame(run);
//设置点击事件。给小鸟3个一眨眼的腾快速度
cvs.add伊芙ntListener(“click”,function(){ bird.speed = -0.3; } ) }) 绘制小鸟,点击小鸟上海飞机创制厂

职能如下:

皇家赌场手机版 16

2.2天空的绘图:

  天空的绘图相比较不难了,只要使用canvas
drawImage的三参数方式就足以(图源,画布上的坐标)。

  那里唯一专注的一点是,无缝滚动的贯彻,对于800*600分辨率这种意况大家成立五个天空对象就可以了,不过为了适配更加多的场合,大家将那些作用写活

  在天空的构造函数上加1个count属性设置多少个天空图片,count属性让实例通过原形中的方法访问。前面涉及到再也出现的本土和管道,都给它们拉长那种设想。

皇家赌场手机版 17var Sky =
function(img,x,speed,ctx) { this.img = img ; this.ctx = ctx; this.x = x;
this.speed = speed; } Sky.prototype.draw = function(){
this.ctx.drawImage( this.img ,this.x,0 ) } Sky.prototype.setCount =
function(count){ Sky.count = count; } Sky.prototype.update =
function(dur){ this.x = this.x+ this.speed * dur; if(this.x<-800){
//天空图片的肥瘦是800 this.x = Sky.count * 800 + this.x;
//当向左移动了一整张图纸后随即切回第1张图片 } } 天空构造函数及运动函数

  同理在主函数中创立一个天空对象,并将更新函数和制图函数放置在主循环的绘图区域;

  setcount是用来设置无缝滚动的

  注意一点:绘制上的图样是有一个层级关系的,不可能把鸟画到天空的上边,那本来最终画鸟了,上边涉及到的遮盖问题不再专门提到。

  那里仅插入部分连锁代码

皇家赌场手机版 18var bird
= new Bird(imgEls[“birds”],150,100,0.0003,0.0006,ctx); var sky1 = new
Sky(imgEls[“sky”],0,-0.3,ctx); var sky2 = new
Sky(imgEls[“sky”],800,-0.3,ctx); //主循环 var preTime= Date.now();
function run(){ var now = Date.now(); dt = now – preTime; preTime = now;
ctx.clearRect(0,0,800,600); //——–图片绘制区域——-
sky1.update(dt); sky1.draw() sky2.update(dt); sky2.draw()
sky1.setCount(2); bird.update(dt) bird.draw();
//————————- 绘制天空

2.3 地面包车型大巴绘图

  和天空的绘图完全一致,由于地点图片尺寸较小,所以大家要多画多少个

皇家赌场手机版 19var Land
= function(img,x,speed,ctx){ this.img = img ; this.x = x; this.speed =
speed; this.ctx = ctx ; } Land.prototype.draw = function(){
this.ctx.drawImage ( this.img , this.x ,488 ) } Land.prototype.setCount=
function(count){ Land.count = count; } Land.prototype.update =
function(dur){ this.x = this.x + this.speed * dur; if (this.x <-
336){ this.x = this.x + Land.count * 336; //无缝滚动的贯彻 } } 地面包车型客车构造函数及运动函数
皇家赌场手机版 20//创立—-放置在创制区域
var land1 = new 迈凯伦(imgEls[“land”],0,-0.3,ctx); var land2 = new
Land(imgEls[“land”],336*1,-0.3,ctx); var land3 = new
Land(imgEls[“land”],336*2,-0.3,ctx); var land4 = new
Land(imgEls[“land”],336*3,-0.3,ctx); //绘制 —-放置在绘制区域
land1.update(dt); land1.draw(); land2.update(dt); land2.draw();
land3.update(dt); land3.draw(); land4.update(dt); land4.draw();
land1.setCount(4); //设置无缝滚动 绘制地面首要代码

2.4绘制管道

  管道的绘图有二个难处是管道高度的明确

  要点:

  •  为了保全游戏可玩性,管道必须有2个定点高度+2个无限制中度,且上下管道之间的留白是一向的小幅度。
  • 管道不是连连的,四个相邻的管道之间有距离
  • 留神管道在无缝播放,抽回后务必交给二个新的自由中度,给用户一种错觉,以为又一个管道飘了过来。

  

皇家赌场手机版 21var Pipe
= function(upImg,downImg,x,speed,ctx){ this.x = x; this.upImg = upImg ;
this.downImg = downImg; this.speed = speed; this.ctx = ctx; this.r =
Math.random() *200 + 100; //随机中度+固定低度 } Pipe.prototype.draw =
function(){ this.ctx.drawImage( this.upImg, this.x , this.r – 420
//管道图纸的长短是420 ) this.ctx.drawImage( this.downImg, this.x ,
this.r +150 //管道中国建工业总会集团的留白是150px ) } Pipe.prototype.setCount =
function( count,gap ){ Pipe.count = count; Pipe.gap = gap;
//那里是这一次绘制的特别之处,加入了区间 } Pipe.prototype.update
=function( dur ){ this.x = this.x + this.speed*dur; if(this.x <-
52){ //管道宽度52px this.x = this.x + Pipe.count * Pipe.gap; //无缝滚动
this.r = Math.random() *200 + 150;
//切换后的管道必须再度设置一个可观,给用户一个新管道的错觉 } } 管道的构造函数及运动函数
皇家赌场手机版 22//创制区域
var pipe1 = new Pipe(imgEls[“pipe2”],imgEls[“pipe1”],400, -0.1,ctx);
var pipe2 = new Pipe(imgEls[“pipe2”],imgEls[“pipe1”],600, -0.1,ctx);
var pipe3 = new Pipe(imgEls[“pipe2”],imgEls[“pipe1”],800, -0.1,ctx);
var pipe4 = new Pipe(imgEls[“pipe2”],imgEls[“pipe1”],1000,-0.1,ctx);
var pipe5 = new Pipe(imgEls[“pipe2”],imgEls[“pipe1”],1200,-0.1,ctx);
//绘制区域 pipe1.update(dt); pipe1.draw(); pipe2.update(dt);
pipe2.draw(); pipe3.update(dt); pipe3.draw(); pipe4.update(dt);
pipe4.draw(); pipe5.update(dt); pipe5.draw(); pipe1.setCount(5,200);
//设置管道数量和间隔 管道的绘图首要代码

到这一步我们的要害画面就营造出来了,是或不是很简短呢O(∩_∩)O~

2.5 判断游戏是不是违犯禁令

皇家赌场手机版 23
//我们改造一下主循环,设置1个gameover为false来支配函数的履行
//任何违规都会触发gameover=true; var gameover = false; if(bird.y < 0
|| bird.y > 488 -45/2 ){ //遇到天和地 gameover = true ; }
if(!gameover){ //借使没有终止游戏则持续玩乐 requestAnimationFrame(run);
} 简单判读gameover

  2. 碰着管道甘休游戏

皇家赌场手机版 24//x和y到时候大家传入小鸟的移位轨迹,每一回重绘管道都有咬定
Pipe.prototype.hitTest = function(x,y){ return (x > this.x && x <
this.x + 52) //在管仲横向中间 &&(! (y >this.r && y < this.r
+150)); //在管敬仲竖向中间 } 判断是不是遭遇管仲
皇家赌场手机版 25 var
gameover = false; gameover = gameover || pipe1.hitTest(bird.x ,bird.y);
gameover = gameover || pipe2.hitTest(bird.x ,bird.y); gameover =
gameover || pipe3.hitTest(bird.x ,bird.y); gameover = gameover ||
pipe4.hitTest(bird.x ,bird.y); gameover = gameover ||
pipe5.hitTest(bird.x ,bird.y); //逻辑终端 if(bird.y < 0 || bird.y
> 488 -45/2 ){ gameover = true ; } if(!gameover){
requestAnimationFrame(run); } 主循环的度量准则构成

皇家赌场手机版 26

到这一步大家的嬉戏实现的差不离了,剩下的便是一些数据的匡正

首要需求改进的一个点是碰上的计量,因为大家拥有的碰撞都以依据小鸟图片的左上角总结的,那样就会有不可相信的难点,通过测试很不难将以此距离加减校正了

 

3.游戏的优化

 小鸟游戏的鸟儿在左右的长河中会随着点击,抬头飞翔,或投降冲刺,如何实现那么些职能啊?

 答案就是运动canvas 坐标系和甄选坐标系的角度
 ctx.translate()和ctx.rotate();

 为了防患全部坐标系的总体旋转运动

 要求在小鸟绘制函数Bird.prototype.draw里前面后端出席ctx.save()
和ctx.restore()来单独主宰小鸟画布

皇家赌场手机版 27Bird.prototype.draw
= function (){ this.ctx.save(); this.ctx.translate(this.x ,this.y);
//坐标移动到小鸟的大旨点上 this.ctx.rotate((Math.PI /6) * this.speed /
0.3 ); //小鸟最大旋转30度,并趁机速度实时改变角度 this.ctx.drawImage(
this.img,52*this.index,0,52,45, -52/2,-45/2,52,45
//这里很要紧的一些是,整个小鸟坐标系开首活动 ) this.ctx.restore(); }
插手小鸟旋转效果

理所当然最终不要忘记对管道碰撞的判断,在此间再勘误3次。

实际上倘若打算出席旋转效果,上3次的匡正不须求,你会发觉许多重复工。

说到底做出的效果如下:

皇家赌场手机版 28

 主体成效和逻辑已经整整兑现。更多的意义能够自行添加。

 假如想协调集会练习一下,请点击游戏细化部分的链接下载相关资料和整体源码。

制作flappy
bird(像素小鸟)全流程,canvasflappy flappy bird制作全流程: 壹 、前言
像素小鸟那个大约的玩耍于二〇一五年在网络上爆红,游戏上…

 

您恐怕感兴趣的篇章:

  • js+html5绘制图片到canvas的法子
  • JS移动端/H5同时选拔多张图纸上传并使用canvas压缩图片
  • js达成canvas保存图片为png格式并下载到本地的艺术
  • Js利用Canvas落成图片压缩功效
  • js完毕canvas图片与img图片的互相转换的演示
  • JavaScript+html5
    canvas达成图片破碎重组动画特效
  • javascript结合canvas完毕图片旋转效果
  • js HTML5
    canvas绘制图片的格局
  • Canvas + JavaScript
    制作图纸粒子效果
  • js
    canvas完毕放大镜查看图片功效
  • JavaScript+Canvas实现彩色图片转换到黑白图片的章程分析

全套源码

<!DOCTYPE html> <html> <head> <title>Flappy
Bird</title> <meta http-equiv=”Content-Type”
content=”text/html; charset=utf-8″ /> <script
type=”text/javascript”> // Edit by xingoo // Fork on my
github: var ctx; var
cwidth = 400; var cheight = 600; var objects = []; var birdIndex = 0;
var ver1 = 10; var ver2; var gravity = 2; var pipe_height = 200; var
velocity = 10; var tid; var score = 0; var isScore = false; var birds =
[“./images/0.gif”,”./images/1.gif”,”./images/2.gif”]; var back = new
Background(0,0,400,600,”./images/bg.png”); var up_pipe = new
UpPipe(0,0,100,200,”./images/pipe.png”); var down_pipe = new
DownPipe(0,400,100,200,”./images/pipe.png”); var ground = new
Background(0,550,400,200,”./images/ground.png”); var bird = new
Bird(80,300,40,40,birds); objects.push(back); objects.push(up_pipe);
objects.push(down_pipe); objects.push(ground); objects.push(bird);
function UpPipe(x,y,width,height,img_src){ this.px = x; this.py = y;
this.pwidth = width; this.pheight = height; this.img_src = img_src;
this.draw = drawUpPipe; } function DownPipe(x,y,width,height,img_src){
this.px = x; this.py = y; this.pwidth = width; this.pheight = height;
this.img_src = img_src; this.draw = drawDownPipe; } function
drawUpPipe(){ var image = new Image(); image.src = this.img_src;
ctx.drawImage(image,150,500,150,800,this.px,this.py,this.pwidth,this.pheight);
} function drawDownPipe(){ var image = new Image(); image.src =
this.img_src;
ctx.drawImage(image,0,500,150,500,this.px,this.py,this.pwidth,this.pheight);
} function Background(x,y,width,height,img_src){ this.bgx = x; this.bgy
= y; this.bgwidth = width; this.bgheight = height; var image = new
Image(); image.src = img_src; this.img = image; this.draw = drawbg; }
function drawbg(){
ctx.drawImage(this.img,this.bgx,this.bgy,this.bgwidth,this.bgheight); }
function Bird(x,y,width,height,img_srcs){ this.bx = x; this.by = y;
this.bwidth = width; this.bheight = height; this.imgs = img_srcs;
this.draw = drawbird; } function drawbird(){ birdIndex++; var image =
new Image(); image.src = this.imgs[birdIndex%3]皇家赌场手机版,;
ctx.drawImage(image,this.bx,this.by,this.bwidth,this.bheight); }
function calculator(){ if(bird.by+bird.bheight>ground.bgy ||
((bird.bx+bird.bwidth>up_pipe.px)&&(bird.by>up_pipe.py)&&(bird.bx+bird.bwidth<up_pipe.px+up_pipe.pwidth)&&(
bird.by<up_pipe.py+up_pipe.pheight))||
((bird.bx+bird.bwidth>up_pipe.px)&&(bird.by>up_pipe.py)&&(bird.bx+bird.bwidth<up_pipe.px+up_pipe.pwidth)&&(
bird.by<up_pipe.py+up_pipe.pheight))||
((bird.bx>down_pipe.px)&&(bird.by>down_pipe.py)&&(bird.bx<down_pipe.px+down_pipe.pwidth)&&(bird.by<down_pipe.py+down_pipe.pheight))||
((bird.bx>down_pipe.px)&&(bird.by+bird.bheight>down_pipe.py)&&(bird.bx<down_pipe.px+down_pipe.pwidth)&&(bird.by+bird.bheight<down_pipe.py+down_pipe.pheight))){
clearInterval(tid); ctx.fillStyle = “rgb(255,255,255)”; ctx.font = “30px
Accent”; ctx.fillText(“You got “+score+”!”,110,100) return; } ver2 =
ver1+gravity; bird.by += (ver2+ver1)*0.5;
if(up_pipe.px+up_pipe.pwidth>0){ up_pipe.px -= velocity;
down_pipe.px -= velocity; }else{ up_pipe.px = 400; down_pipe.px =
400; up_pipe.pheight = 100+Math.random()*200; down_pipe.py =
up_pipe.pheight+pipe_height; down_pipe.pheight = 600-down_pipe.py;
isScore = true; } if(isScore && bird.bx>up_pipe.px+up_pipe.pwidth){
score += 1; isScore = false; if(score>0 && score%10 === 0){
velocity++; } } ctx.fillStyle = “rgb(255,255,255)”; ctx.font = “30px
Accent”; if(score>0){
score%10!==0?ctx.fillText(score,180,100):ctx.fillText(“Great!”+score,120,100);
} } function drawall(){ ctx.clearRect(0,0,cwidth,cheight); var i;
for(i=0;i<objects.length;i++){ objects[i].draw(); } calculator(); }
function keyup(e){ var e = e||event; var currKey =
e.keyCode||e.which||e.charCode; switch (currKey){ case 32: bird.by -=
80; break; } } function init(){ ctx =
document.getElementById(‘canvas’).getContext(‘2d’); document.onkeyup =
keyup; drawall(); tid = setInterval(drawall,80); } </script>
</head> <body onLoad=”init();”> <canvas id=”canvas”
width=”400″ height=”600″ style=”margin-left:200px;”> Your browser is
not support canvas! </canvas> </body> </html>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
<!DOCTYPE html>
<html>
<head>
    <title>Flappy Bird</title>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <script type="text/javascript">
        // Edit by xingoo
        // Fork on my github:https://github.com/xinghalo/CodeJS/tree/master/HTML5
        var ctx;
        var cwidth = 400;
        var cheight = 600;
        var objects = [];
        var birdIndex = 0;
        var ver1 = 10;
        var ver2;
        var gravity = 2;
        var pipe_height = 200;
        var velocity = 10;
        var tid;
        var score = 0;
        var isScore = false;
        var birds = ["./images/0.gif","./images/1.gif","./images/2.gif"];
        var back = new Background(0,0,400,600,"./images/bg.png");
        var up_pipe = new UpPipe(0,0,100,200,"./images/pipe.png");
        var down_pipe = new DownPipe(0,400,100,200,"./images/pipe.png");
        var ground = new Background(0,550,400,200,"./images/ground.png");
        var bird = new Bird(80,300,40,40,birds);
        objects.push(back);
        objects.push(up_pipe);
        objects.push(down_pipe);
        objects.push(ground);
        objects.push(bird);
        function UpPipe(x,y,width,height,img_src){
            this.px = x;
            this.py = y;
            this.pwidth = width;
            this.pheight = height;
            this.img_src = img_src;
            this.draw = drawUpPipe;
        }
        function DownPipe(x,y,width,height,img_src){
            this.px = x;
            this.py = y;
            this.pwidth = width;
            this.pheight = height;
            this.img_src = img_src;
            this.draw = drawDownPipe;
        }
        function drawUpPipe(){
            var image = new Image();
            image.src = this.img_src;
            ctx.drawImage(image,150,500,150,800,this.px,this.py,this.pwidth,this.pheight);
        }
        function drawDownPipe(){
            var image = new Image();
            image.src = this.img_src;
            ctx.drawImage(image,0,500,150,500,this.px,this.py,this.pwidth,this.pheight);
        }
        function Background(x,y,width,height,img_src){
            this.bgx = x;
            this.bgy = y;
            this.bgwidth = width;
            this.bgheight = height;
            var image = new Image();
            image.src = img_src;
            this.img = image;
            this.draw = drawbg;
        }
        function drawbg(){
            ctx.drawImage(this.img,this.bgx,this.bgy,this.bgwidth,this.bgheight);
        }
        function Bird(x,y,width,height,img_srcs){
            this.bx = x;
            this.by = y;
            this.bwidth = width;
            this.bheight = height;
            this.imgs = img_srcs;
            this.draw = drawbird;
        }
        function drawbird(){
            birdIndex++;
            var image = new Image();
            image.src = this.imgs[birdIndex%3];
            ctx.drawImage(image,this.bx,this.by,this.bwidth,this.bheight);
        }
        function calculator(){
            if(bird.by+bird.bheight>ground.bgy ||
                ((bird.bx+bird.bwidth>up_pipe.px)&&(bird.by>up_pipe.py)&&(bird.bx+bird.bwidth<up_pipe.px+up_pipe.pwidth)&&(    bird.by<up_pipe.py+up_pipe.pheight))||
                ((bird.bx+bird.bwidth>up_pipe.px)&&(bird.by>up_pipe.py)&&(bird.bx+bird.bwidth<up_pipe.px+up_pipe.pwidth)&&(    bird.by<up_pipe.py+up_pipe.pheight))||
                ((bird.bx>down_pipe.px)&&(bird.by>down_pipe.py)&&(bird.bx<down_pipe.px+down_pipe.pwidth)&&(bird.by<down_pipe.py+down_pipe.pheight))||
                ((bird.bx>down_pipe.px)&&(bird.by+bird.bheight>down_pipe.py)&&(bird.bx<down_pipe.px+down_pipe.pwidth)&&(bird.by+bird.bheight<down_pipe.py+down_pipe.pheight))){
                clearInterval(tid);
                ctx.fillStyle = "rgb(255,255,255)";
                ctx.font = "30px Accent";
                ctx.fillText("You got "+score+"!",110,100)
                return;
            }
            ver2 = ver1+gravity;
            bird.by += (ver2+ver1)*0.5;
            if(up_pipe.px+up_pipe.pwidth>0){
                up_pipe.px -= velocity;
                down_pipe.px -= velocity;
            }else{
                up_pipe.px = 400;
                down_pipe.px = 400;
                up_pipe.pheight = 100+Math.random()*200;
                down_pipe.py = up_pipe.pheight+pipe_height;
                down_pipe.pheight = 600-down_pipe.py;
                isScore = true;
            }
            if(isScore && bird.bx>up_pipe.px+up_pipe.pwidth){
                score += 1;
                isScore = false;
                if(score>0 && score%10 === 0){
                    velocity++;
                }
            }
            ctx.fillStyle = "rgb(255,255,255)";
            ctx.font = "30px Accent";
            if(score>0){
                score%10!==0?ctx.fillText(score,180,100):ctx.fillText("Great!"+score,120,100);
            }
        }
        function drawall(){
            ctx.clearRect(0,0,cwidth,cheight);
            var i;
            for(i=0;i<objects.length;i++){
                objects[i].draw();
            }
            calculator();
        }
        function keyup(e){
            var e = e||event;
               var currKey = e.keyCode||e.which||e.charCode;
               switch (currKey){
                case 32:
                    bird.by -= 80;
                    break;
            }
        }    
        function init(){
            ctx = document.getElementById(‘canvas’).getContext(‘2d’);
            document.onkeyup = keyup;
            drawall();
            tid = setInterval(drawall,80);
        }
    </script>
</head>
<body onLoad="init();">
<canvas id="canvas" width="400" height="600" style="margin-left:200px;">
    Your browser is not support canvas!
</canvas>
</body>
</html>

接下去是bird的draw属性,这性格情首借使将bird给画出来

总结

在攻读玩乐支付的时候,笔者恍然怀恋起大学的物理。当时很迷惑,学计算机学如何物理,后来再触及游戏开发才清楚,没有一定的物理知识,根本不可能模拟游戏中的各类场景。

而因此这一个大约的小游戏,也捡起来了成千成万旧文化。

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

参考

【1】:Canvas参考手册

【2】:《HTML5戏耍支付》

【3】:EdisonChou的FlappyBird

2 赞 6 收藏
评论

皇家赌场手机版 29

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

 

接下去就是bird的jump属性,那几个天性重倘若控制bird的大跌,模仿小鸟的下跌

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

科学,如故如此简单,便是修改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.   
  9.                 return this;  
  10.             };  

是否认为和bird很像,可是就是多了visible属性,那本性情是决定盒子的看见与否,在玩耍中的小鸟通过的的水管之间的空隙就是靠它了,

 

要么要定义它多少个法子,不对,它惟有三个情势

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

有没有觉得这一个措施和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.   
  11.                 for (var i = 0; i < maxNum; i++) {  
  12.                     boxTmp = new Box(posX, i * boxH);  
  13.                     boxList.push(boxTmp);  
  14.                 }  
  15.   
  16.                 this.obj = boxList;  
  17.                 this.boxW = boxW;  
  18.                 return this;  
  19.             };  

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来1遍遍历输出,当然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.   
  7.                 var rand = Math.floor(Math.random() *  5) + 1;  
  8.                 // console.log(rand);  
  9.                 this.obj[rand].visible = false;  
  10.                 this.obj[rand + 1].visible = false;  
  11.   
  12.                 return this;  
  13.             };  

终极2性情质是活动方法,那是让水管实行左右运动的

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

ok
基本那样ok了,可是大家是还是不是忘了什么事物啊,想起来了,我们还没有进行碰撞检查和测试呢,假诺不开始展览碰撞检查和测试,那岂不是开挂了,那本来是不行的

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

那样就基本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.             // 绑定鼠标事件  
  16.             document.onclick = function () {  
  17.                 bird.y -= 25;  
  18.             }  
  19.             function start() {  
  20.                 requestId = window.requestAnimationFrame(render);  
  21.                 stopped = false;  
  22.                 // console.log(requestId);  
  23.   
  24.             }  
  25.   
  26.             function stop() {  
  27.                 if (requestId) {  
  28.                     window.cancelAnimationFrame(requestId);  
  29.                 }  
  30.                 stopped = true;  
  31.                 // console.log(requestId);  
  32.             }  
  33.   
  34.             start();  

效用如下图所示

 

皇家赌场手机版 30

完全代码请访问小编的github

Leave a Comment.