来自 公司简介 2019-09-25 06:35 的文章
当前位置: 澳门太阳娱乐手机登录 > 公司简介 > 正文

像素小鸟,Canvas前端游戏开辟

[Canvas前端游戏支付]——FlappyBird详解

2016/01/03 · HTML5 · Canvas

原稿出处: xingoo   

直接想协和做点小东西,直到日前看了本《HTML5游戏开垦》,才领会游戏支付中的一丢丢入门知识。

本篇就针对学习的多少个样例,本身出手实行,做了个FlappyBird,源码分享在度盘 ;也得以仿效github,里面有更加多的娱乐样例。

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

娱乐截图

图片 1

图片 2

flappy bird制作全流程:

图片 3

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每种绘制都以单独的操作。比方下图的多少个绘制图形,第三个会以掩盖的款式绘制,因而绘制图形的一一就显得比较重大了。

图片 4

一、前言

像素小鸟那一个轻易的玩乐于二零一五年在网络上爆红,游戏上线一段时间内appleStore上的下载量一度达到5000万次,风靡不时,

如今移动web的广泛为这么未有复杂逻辑和精密动画效果,但是乐趣十足的小游戏提供了可观的蒙受,

再就是凭仗各大社交软件平台的传播效应,创新意识不断的小游戏有着精良的经营贩卖效果与利益,得到了过多的关注。

原先在英特网查询了广大关于这些小游戏的材质,但是基本上乌烟瘴气,本身的三结合有关学科将那几个游戏的严重性框架整理出来,供大家一齐读书。

canvas之drawImage()

本篇的玩耍开辟中,首要采纳的是基于图片绘制的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中,第一组x,y,width,height则钦赐了裁剪图片的坐标尺寸,这在使用多元素的矢量图时很常用。举个例子:

图片 5

地点的图样中为了减少图片财富的央浼数量,把广大的要素放在了三个图片中,此时就要求通过裁剪的秘技,获取钦定的图样成分。

二、技能中央

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

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()方法,在必然间隔时间内,试行一次重绘

重绘的时候会先祛除画面中的全数因素,然后根据新的因素的坐标一遍绘制图形,那样就能够产出活动的效果。

三、思路整理

里丑捧心小鸟重力

由于这一个娱乐不涉及小鸟横向的运动,由此假使模拟出小鸟下降的动作以及上升的动作就能够了。

图片 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;

全体游戏的逻辑相比较轻巧:

第一游戏法规:鸟撞到管道上,地上要身故,飞到显示器外要身故。

说不上:鸟在飞翔的历程中,会掉落,类似落体运动,须求游戏用户不断点击荧屏让鸟向上海飞机创立厂。

再次正是:鸟和背景元素的相持移动的长河,鸟不动,背景左移。

碰撞检验

打闹中型Mini鸟碰到管敬仲恐怕地面都会算游戏甘休:

图片 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将流程以脑图的情势绘制下来,分块去做,不断细化记录自个儿的笔触,最后表现的机能如下:

(顺序依据图片中的序号去看  脑图、素材、及全部源码下载地址: 想演练的同桌可以点这里)

脑图分为三大块:1、准备阶段 2、主函数 3、游戏优化。

图片 9

图片 10

 

 

分数计算

分数的一个钱打二十七个结与碰撞检查测验类似,设置多少个开关,当管仲重新出现时,设置为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 preTime= 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、主函数分为两有个别作用,简单说就是把图画上去,然后管理动态效果,再推断一下是否违禁。

2.1 小鸟的绘图:

  小鸟自己有二个双翅扇动的职能,和叁个低沉的长河。

  羽翼扇动的历程是一张Smart图三幅画面包车型地铁的切换(设置二个index属性,调节Smart图的岗位),下落进度是其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; //用于创设小鸟扇羽翼的动作 } Bird.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; preTime = now; ctx.clearRect(0,0,800,600); //--------图片绘制区域------- bird.update(dt) bird.draw(); //------------------------- requestAnimationFrame(run); } requestAnimationFrame(run); //设置点击事件。给小鸟一个时而的上进速度 cvs.addEventListener("click",function(){ bird.speed = -0.3; } ) }) 绘制小鸟,点击小鸟上飞

功用如下:

图片 16

2.2天空的绘图:

  天空的绘图比较轻易了,只要使用canvas drawImage的三参数形式就能够(图源,画布上的坐标)。

  这里唯一专一的少数是,无缝滚动的完结,对于800*600分辨率这种情景大家创立三个天空对象就足以了,可是为了适配越来越多的境况,大家将那个功效写活

  在天宇的构造函数上加三个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; //当向左移动了一整张图纸后当即切回第一张图片 } } 天空构造函数及运动函数

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

  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 Land(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绘制管道

  管道的绘图有多少个难点是管道中度的规定

  要点:

  •  为了维持游戏可玩性,管道必得有二个恒定中度+三个率性中度,且上下管道之间的留白是定位的宽窄。
  • 管道不是三翻五次的,多少个相邻的管道之间有距离
  • 专心管道在无缝播放,抽回后必需交给四个新的专擅中度,给客商一种错觉,认为又一个管道飘了还原。

  

图片 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 //大家改动一下主循环,设置八个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(); } 参预小鸟旋转效果

理之当然最后不要忘记对管道碰撞的判定,在那边再考订贰回。

实际上要是筹算加入旋转效果,上一遍的匡正不必要,你会意识很多种复工。

终极做出的效劳如下:

图片 28

 主体职能和逻辑已经全部完成。越来越多的效益能够自行加多。

 就算想本人练习一下,请点击游戏细化部分的链接下载相关质地和任何源码。

制作flappy bird(像素小鸟)全流程,canvasflappy flappy bird制作全流程: 一、前言 像素小鸟那么些轻便的游戏于贰零壹肆年在网络上爆红,游戏上...

全套源码

<!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>

总结

在攻读玩乐开辟的时候,小编忽然思念起高校的大意。当时很纳闷,学计算机学什么物理,后来再触及游戏支付才理解,未有一定的物理知识,根本不可能模拟游戏中的种种场景。

而透过那么些简单的小游戏,也捡起来了广大旧文化。

参考

【1】:Canvas参谋手册

【2】:《HTML5玩耍开垦》

【3】:EdisonChou的FlappyBird

2 赞 6 收藏 评论

图片 29

本文由澳门太阳娱乐手机登录发布于公司简介,转载请注明出处:像素小鸟,Canvas前端游戏开辟

关键词: