菜单

澳门金沙国际用html5落到实处的flappy-bird

2019年3月19日 - 金沙前端

游玩截图

澳门金沙国际 1

澳门金沙国际 2

一、前言

像素小鸟这几个简单的游艺于二零一四年在互联网上爆红,游戏上线一段时间内appleStore上的下载量一度达到六千万次,风靡一时,

多年来移动web的普及为这么没有复杂逻辑和迷你动画效果,不过趣味十足的小游戏提供了特出的环境,

并且凭借各大社交软件平台的传播效应,创新意识不断的小游戏有着雅观的经营销售效益,获得了很多的爱抚。

先前在网上查询了成都百货上千有关那么些小游戏的材料,然而大多杂乱无章,自身的构成有关课程将以此娱乐的第壹框架整理出来,供大家一起学学。

接下去是pipe的目的,它但是是box的一个聚众

复制代码 代码如下:

总结

在学习玩乐支付的时候,笔者恍然想念起大学的大体。当时很迷惑,学电脑学如何物理,后来再接触游戏支付才理解,没有一定的物理知识,根本不可能模拟游戏中的种种场景。

而经过这一个大致的小游戏,也捡起来了重重旧文化。

二 、技术中央

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

  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.             }  

同伴们拿去摸索啊,希望大家能够欣赏,有疑问就给自身留言吗。

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);

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

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

澳门金沙国际 3

地方的图纸中为了减小图片财富的央浼数量,把许多的因素放在了1个图片中,此时就供给通过裁剪的不二法门,获取内定的图片成分。

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

意义如下图所示

您大概感兴趣的小说:

FlappyBird原理分析

实际上那么些娱乐很粗大略,一张图就能够看懂当中的神妙:

澳门金沙国际 4

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

鸟类唯有上和下八个动作,能够因而操纵小鸟的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;
            }

相当粗略吗!

出于该游戏一共就那多少个成分,因而把他们都放入1个Objects数组中,通过setInteral()方法,在一定间隔时间内,执行二遍重绘

重绘的时候会先祛除画面中的全体因素,然后依据新的成分的坐标3次绘制图形,那样就会并发活动的效能。

叁 、思路整理

有没有认为那几个艺术和bird的draw方法一样,没错是一样的,其实本身应该让box继承bird对象,那样自个儿的代码有能够少几行了

参考

【1】:Canvas参考手册

【2】:《HTML5游玩开发》

【3】:EdisonChou的FlappyBird

2 赞 6 收藏
评论

澳门金沙国际 5

 四 、游戏实现:

未来组合脑图来逐步落到实处大家的游玩。

1.安装canvas画布,准备图片数据,当图片加载成功后执行回调函数;

澳门金沙国际 6<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的时候再进行主函数;

澳门金沙国际 7function
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阿秒绘制2回的动画片是特别不可相信的;

       requestAnimationFrame()这么些定时器的裨益是基于浏览器的天性来执行2个函数,大家用来获取三次绘制的间隔时间;

       移动距离的盘算改变成速度×间隔时间的法门,来缓解绘图不确切的难题。

澳门金沙国际 8var
preTime= Date.now(); //获取当前岁月 function run(){ var now =
Date.now(); //获取最新时刻 dt = now – pre提姆e; //获取时间距离 preTime =
now; //更新当前时刻 ctx.clearRect(0,0,800,600); //清空画布
//——————————————— 绘制代码执行区域
//———————————————–
requestAnimationFrame(run); //再一次执行run函数 }
requestAnimationFrame(run); //第三回执行run函数; 设置绘制格局

② 、主函数分为两局地作用,不难说正是把图画上去,然后处理动态效果,再判断一下是或不是违犯禁令。

2.1 小鸟的绘图:

  小鸟自己有2个翅膀扇动的效率,和1个骤降的进程。

  翅膀扇动的长河是一张天使图三幅画面包车型客车的切换(设置2个index属性,控制天使图的任务),降低进度是其y坐标在画布上的活动();

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

  那里必要专注几点:

澳门金沙国际 9var 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; } 小鸟的构造函数及动作控制

 
构造四个鸟类,并且将其动作刷新函数和制图函数放置在大家地点提到的绘图区域,此后结构出的接近对象都以这般的操作步骤:

 
那里要求专注的有个别是,如何让鸟儿顺畅的进化飞翔,其实仍旧情理知识,由于加快度的功效,大家给小鸟三个前进的顺时速度就能够了。

澳门金沙国际 10load(imglist
,function(imgEls){ //创立对象 //在主函数中开创一个鸟类 var bird = new
伯德(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.add伊芙ntListener(“click”,function(){ bird.speed = -0.3; } ) }) 绘制小鸟,点击小鸟上海飞机创建厂

功效如下:

澳门金沙国际 11

2.2天空的绘图:

  天空的绘图比较简单了,只要使用canvas
drawImage的三参数情势就能够(图源,画布上的坐标)。

  那里唯一专注的有些是,无缝滚动的完成,对于800*600分辨率那种景色我们创造多少个天空对象就能够了,可是为了适配更加多的景况,大家将以此效应写活

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

澳门金沙国际 12var 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是用来安装无缝滚动的

  注意一点:绘制上的图形是有二个层级关系的,不可能把鸟画到天空的底下,那本来最后画鸟了,上面涉及到的遮盖难题不再专门提到。

  这里仅插入部分连锁代码

澳门金沙国际 13var 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 地面包车型大巴绘图

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

澳门金沙国际 14var 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; //无缝滚动的兑现 } } 地面包车型地铁构造函数及运动函数
澳门金沙国际 15//创制—-放置在创造区域
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制图管道

  管道的绘图有三个困难是管道中度的明确

  要点:

  

澳门金沙国际 16var 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;
//切换后的管道必须再度安装2个惊人,给用户三个新管道的错觉 } } 管道的构造函数及运动函数
澳门金沙国际 17//成立区域
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 判断游戏是不是违犯禁令

澳门金沙国际 18
//大家改造一下主循环,设置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. 相见管道停止游戏

澳门金沙国际 19//x和y到时候我们传入小鸟的运动轨迹,每一次重绘管道都有咬定
Pipe.prototype.hitTest = function(x,y){ return (x > this.x && x <
this.x + 52) //在管仲横向中间 &&(! (y >this.r && y < this.r
+150)); //在管敬仲竖向中间 } 判断是还是不是碰到管仲
澳门金沙国际 20 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); } 主循环的判定标准构成

澳门金沙国际 21

到这一步大家的娱乐形成的大半了,剩下的正是有的数码的匡正

重在需求校订的三个点是撞倒的乘除,因为大家全体的碰撞都以比照小鸟图片的左上角总括的,那样就会有不可相信的题材,通过测试很简单将那个距离加减改正了

 

3.游戏的优化

 小鸟游戏的小鸟在前后的经过中会随着点击,抬头飞翔,或妥胁冲刺,怎样达成这么些功用啊?

 答案正是活动canvas 坐标系和挑选坐标系的角度
 ctx.translate()和ctx.rotate();

 为了防止万一全部坐标系的一体化旋转运动

 必要在小鸟绘制函数Bird.prototype.draw里前边后端插手ctx.save()
和ctx.restore()来单独主宰小鸟画布

澳门金沙国际 22Bird.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(); }
出席小鸟旋转效果

本来最后不要遗忘对管道碰撞的论断,在此处再核对叁次。

实在借使打算加入旋转效果,上贰次的勘误不须求,你会发现许多重复工。

最后做出的功力如下:

澳门金沙国际 23

 主体效能和逻辑已经整整贯彻。越多的功能能够自行添加。

 要是想自个儿演习一下,请点击游戏细化部分的链接下载相关资料和成套源码。

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

诸如此类就基本ok了,接下去也只是一些,开端化而已,这一个一贯上代码吧

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>

一切游戏的逻辑比较简单:

第1游戏规则:鸟撞到管道上,地上要身故,飞到显示器外要与世长辞。

附带:鸟在飞翔的历程中,会落下,类似落体运动,要求玩家不断点击显示屏让鸟向上海飞机创设厂。

再也正是:鸟和背景成分的绝对移动的历程,鸟不动,背景左移。

完整代码请访问笔者的github

canvas标签唯有八个天性:width和height,用来设定画布的宽和高,要是没有经过标签属性或许脚本来设置,暗许为300*150;

分数总结

分数的盘算与碰撞检查和测试类似,设置七个开关,当管仲重新出现时,设置为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。

将一切娱乐细化:

咱俩接纳面向对象的思路来创制,具体的事物用构造函数来创制,方法放到构造函数的本色对象中。

二十二十五日游细化这几个历程不是简单的,即使在尚未相关教导的事态下,自个儿要持续的结缘本人的想法去试错。

自家使用的艺术是利用Xmind将流程以脑图的款型绘制下来,分块去做,不断细化记录本人的思绪,最终表现的功效如下:

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

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

澳门金沙国际 24

澳门金沙国际 25

 

 

  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.             }  

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]) {
            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

碰撞检查和测试

玩耍中型小型鸟遭遇管敬仲可能当地都会算游戏停止:

澳门金沙国际 26

其中条件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

比方满足那多个原则,纵然游戏甘休,会消除循环以及提示游戏结束音讯。

flappy bird制作全流程:

澳门金沙国际 27

接下去是bird的draw属性,这几个脾性重若是将bird给画出来

好了,canvas的介绍就先到那边,上边我们来看望javascript结合canvas完结图片的剪裁代码:

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

2016/01/03 · HTML5 ·
Canvas

原稿出处: xingoo   

直接想协调做点小东西,直到最近看了本《HTML5游玩支付》,才打听游戏支付中的一小点入门知识。

本篇就本着学习的多少个样例,自身入手实践,做了个FlappyBird,源码共享在度盘 ;也得以参照github,里面有越来越多的游乐样例。

  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.             };  

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各类绘制都以独自的操作。比如下图的五个绘制图形,第③个会以遮盖的方式绘制,因而制图图形的依次就展现12分至关心珍视要了。

澳门金沙国际 28

宪章小鸟重力

出于这几个游戏不关乎小鸟横向的移动,由此一旦模拟出小鸟降低的动作以及上涨的动作就能够了。

澳门金沙国际 29

上升:那个非常粗大略,只要把小鸟的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 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();  
  1. Bird.prototype.jump = function () {  
  2.                 this.y += this.yDir;  
  3.                 this.draw();  
  4.   
  5.                 return this;  
  6.             }  

html代码作者就不写了,大家也都清楚,若是你连html代码也供给的话,那您接下去也就没要求看了,还不如直接跳转到w3school.com.cn。

相关文章

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图