<body>

canvas的默认大小,以及如何改变画布的大小:https://blog.csdn.net/csm0912/article/details/52963240

<!-- <canvas id="cvs" width="800px" height="600px"></canvas> -->
<canvas id="cvs"></canvas>
</body>
<script>
//加载所有图片的函数:imgObj是存放图片的对象,fn是回调函数
function LoadImage(imgObj,fn){
//用来存放加载完的图片
var imgobj={};
//用来动态生成图片
var tempImg;
//记录要加载的数量
// console.log(imgObj.length);  输出结果是undefined
var imgLength=0;
//记录已经加载完毕的数量
var loaded=0;
for(var key in imgObj){
imgLength++;
//动态创建一个image
tempImg=new Image();
//所有图片要监听的onload事件
tempImg.οnlοad=function(){
loaded++;
if(loaded>=imgLength){
//把加载好的数据传入回调函数
fn(imgobj);
}
};
tempImg.src=imgObj[key];
imgobj[key]=tempImg;
}
}
</script>
<script>
//绘制背景
function Sky(ctx,img,speed){
this.ctx=ctx;
this.img=img;
this.width=img.width;
this.height=img.height;
this.speed=speed||10;
Sky.len++;
this.x=this.img.width*(Sky.len-1);
this.y=0;

}

对象的静态属性:http://www.jb51.net/article/64278.htm

//静态变量,每创建一个sky实例都会加1,用来确定x的位置
Sky.len = 0;
Sky.prototype={
construct:Sky,
draw:function(){
this.ctx.drawImage(this.img,this.x,this.y);
},
update:function(){
//让背景移动起来
this.x-=this.speed;
//如果x移出画布(整个移出,x一定小于负的宽度,令这个图片拼到最后面的图片的后面,给现在的x加上一共多少个图片的宽度即可)
this.x=this.x<=-this.width?this.x+this.width*Sky.len:this.x
}
}
//绘制小鸟widthFrame:图片一行有几个小鸟
function Bird(ctx,img,widthFrame,heightFrame,x,y){
this.ctx=ctx;
this.img=img;
this.widthFrame=widthFrame;
this.heightFrame=heightFrame;
this.x=x;
this.y=y;
this.width=this.img.width / this.widthFrame;
this.height=this.img.height / this.heightFrame;
//当前小鸟的帧数
this.currentFrame=0;
//小鸟下落的速度是speed,下落的加速度是speedPlus
this.speed=2;
this.speedPlus=0.2;
}
Bird.prototype={
construct:Sky,
//让小鸟根据speed调整旋转角度
draw:function(){
var baseRadian=Math.PI/180*10;
var rotateRadian=baseRadian*this.speed;
//保存小鸟还没开始旋转时的状态
this.ctx.save();
//1.先把坐标轴平移到小鸟的中心点
//2.根据speed旋转小鸟的度数,speed=1时,旋转90度,超过45度,就是45度
//3.绘制小鸟,将小鸟的x,y设置为宽度和高度的一半
this.ctx.translate(this.x+this.width/2,this.y+this.height/2);
 
if(rotateRadian>=Math.PI/180*45){
rotateRadian=Math.PI/180*45;
}
this.ctx.rotate(rotateRadian);
// this.ctx.rotate(Math.PI/180*45);

this.ctx.drawImage(this.img,this.width*this.currentFrame,0,this.width,this.height,-this.width/2,-this.height/2,this.width,this.height);
// this.ctx.drawImage(this.img,this.width*this.currentFrame,0,this.width,this.height,this.x,this.y,this.width,this.height);
this.ctx.restore();
},
// 小鸟不需要往前跑,背景,land,pipe在动,小鸟往下落就可以
update:function(){
this.currentFrame++;
this.currentFrame=this.currentFrame>=this.widthFrame?0:this.currentFrame;
// this.currentFrame=++this.currentFrame>=this.widthFrame?0:this.currentFrame;
this.y+=this.speed;
this.speed+=this.speedPlus;
},
//监听点击事件,点击画布speed变成反方向,因此y再加speed就会往上跑,且越往上speed越小,就变成向上的减速运动
_bind:function(){
var that =this;
this.ctx.canvas.addEventListener("click",function(){
that.speed=-3;
});
}
}
//大地 和背景是类似的
function Land(ctx,img,speed){
this.ctx=ctx;
this.img=img;
this.speed=speed||2;
this.height=this.img.height;
this.y=this.ctx.canvas.height-this.img.height;
Land.len++;
this.x=this.img.width*(Land.len-1);
}
Land.len=0;
Land.prototype={
construct:Land,
draw:function(){
this.ctx.drawImage(this.img,this.x,this.y);
},
update:function(){
this.x-=this.speed;
this.x=this.x<=-this.img.width?this.x+this.img.width*Land.len:this.x;
}
}
//管道 两张图片,上下管道,space表示中间的间隙,land的高度
function Pipe(ctx,img1,img2,space,speed,landHeight){
this.ctx=ctx;
this.img1=img1;
this.img2=img2;
this.space=space;
this.speed=speed||2;
this.landHeight=landHeight;
this.width=this.img2.width;
this.height=this.img2.height;
this.y1=0;
this.y2=0;
this.height2=this.img2.height;
this.minHeight=100;

Pipe.len++;

// 中间隔3个管子,再加上本身宽度一共4个

this.x=500+this.width*4*(Pipe.len-1);
//init在创建实例的时候调用一次,不是在setinterval中调用,否则y值会一直变化
this.init();
}
Pipe.len=0;
Pipe.prototype={
construct:Pipe,
init:function(){
var maxHeight=this.ctx.canvas.height-this.minHeight-this.landHeight-this.space;
var randomHeight=Math.random()*maxHeight;
if(randomHeight<this.minHeight){
randomHeight=this.minHeight;
}
this.y1=randomHeight-this.img1.height;
this.y2=randomHeight+this.space;
//注意不能直接drawImage(this.img2,this.x,this.y2);
//因为下面管子的下半部分应该被截取了,但是它现在是全部显示的
//得做计算求出现在需要剩余的下管子的高度
this.height2=this.ctx.canvas.height-this.y2-this.landHeight;
},
draw:function(){
this.ctx.drawImage(this.img1,this.x,this.y1);
this.ctx.drawImage(this.img2,this.x,this.y2,this.width,this.height2);
this.drawPath();
},
update:function(){
this.x-=this.speed;
if(this.x<=-this.width){
//从画布中出去的管子再重新初始化
this.init();
this.x+=this.width*4*Pipe.len;
}
},
//画管道的路径
drawPath:function(){
this.ctx.rect(this.x,this.y1,this.width,this.height);
this.ctx.rect(this.x,this.y2,this.width,this.height2);
// this.ctx.stroke();
}
}
</script>
<script>
var cvs =document.getElementById('cvs');
var ctx =cvs.getContext("2d");
LoadImage({
bird:"image/birds.png",
sky:"image/sky.png",
pipe1:"image/pipe2.png",
pipe2:"image/pipe1.png",
land:"image/land.png"
},function(imgObj){
//这两行根据背景的高宽设置画布的高宽应该写在最上面,如果写在下面就会先创建land实例,此时画布的高宽还没有设置,是默认,计算的land的y就不对
cvs.width=imgObj.sky.width;
cvs.height=imgObj.sky.height;
var sky=new Sky(ctx,imgObj.sky,10);
var sky1=new Sky(ctx,imgObj.sky,10);
var bird=new Bird(ctx,imgObj.bird,3,1,10,10);
var land=new Land(ctx,imgObj.land,10);
var land1=new Land(ctx,imgObj.land,10);
var land2=new Land(ctx,imgObj.land,10);
//3个land已经可以填满画布的宽,但是动起来时,第一张还没有完全出去,最右边已经出来了,就会导致右边空出来一块一会儿才被补上。需要4张图片
var land3=new Land(ctx,imgObj.land,10);
var pipe=new Pipe(ctx,imgObj.pipe1,imgObj.pipe2,100,5,land.height);
var pipe1=new Pipe(ctx,imgObj.pipe1,imgObj.pipe2,100,5,land.height);
var pipe2=new Pipe(ctx,imgObj.pipe1,imgObj.pipe2,100,5,land.height);
var pipe3=new Pipe(ctx,imgObj.pipe1,imgObj.pipe2,100,5,land.height);
var timer=setInterval(function(){
//定时器一开始就进行判断,小鸟是否碰壁,如果碰壁就清除定时器
//小鸟的中心点
var bordCoreX=bird.x+bird.width/2;
var bordCoreY=bird.y+bird.height/2;
//如果小鸟的中心点在路径内,或者超过画布最上面,或者落地,都清除定时器
//isPointInPath(x,y)方法,判断点(x,y)在不在路径中
// if(ctx.isPointInPath(bordCoreX,bordCoreY)||bordCoreY<0||bordCoreY>(ctx.canvas.height-land.height)){
if(ctx.isPointInPath(bordCoreX,bordCoreY)||bordCoreY<0||bordCoreY>(land.y)){
clearInterval(timer);
ctx.fillStyle="rgba(100,100,100,0.8)";
ctx.fillRect(0,0,ctx.canvas.width,ctx.canvas.height);
//不显示字!因为出现字以后跳出判断,接着sky.draw(),把字给覆盖了
ctx.textAlign="center";
ctx.textBaseline="middle";
ctx.fillStyle="red";
ctx.font="900 40px 微软雅黑";
ctx.fillText("GAME OVER!!",ctx.canvas.width/2,ctx.canvas.height/2);
// return的作用是跳出这个判断,不执行下面的代码,不会覆盖掉文字
return;
}
sky.draw();
sky.update();
sky1.draw();
sky1.update();
bird.draw();
bird.update();
bird._bind();
land.draw();
land1.draw();
land2.draw();
land3.draw();
land.update();
land1.update();
land2.update();
land3.update();
//要在这几个管道一起的前面清楚路径,如果每次画draw就会只有一个路径,所以要一起清,不清的话每次update就会产生新的路径。
ctx.beginPath();
pipe.draw();
pipe.update();
pipe1.draw();
pipe1.update();
pipe2.draw();
pipe2.update();
pipe3.draw();
pipe3.update();
},50);

});
</script>

【练习】canvas——flappyBird相关推荐

  1. 前端实战小案例--canvas实战之FlappyBird小游戏

    前端实战小案例--canvas实战之FlappyBird小游戏 想练习更多前端案例,请进个人主页,点击前端实战案例->传送门 觉得不错的记得点个赞?支持一下我0.0!谢谢了! 不积跬步无以至千里 ...

  2. 微信小游戏开发Canvas资源汇总

    Demo: 微信小程序demo组件:股票分时图 微信小程序小组件:仿直播点赞气泡效果,基于Canvas 优质demo推荐:二维码生成器:使用canvas与纯JS版二维码生成 微信小程序学习用完整dem ...

  3. 用canvas和原生JS写的一个flappy bird游戏

    为什么80%的码农都做不了架构师?>>>    <!DOCTYPE html> <html> <head>     <title>&l ...

  4. 手写经典游戏 - FlappyBird

    目录 一.FlappyBird简介 二.技术铺垫 1. canvas(画布) 2. 基于setInterval的动画实现 三.代码实现 1. 定义画布 2. 初始化参数 3. 首绘 4. 启动游戏 5 ...

  5. Android60分钟搞定《FlappyBird》飞扬的小鸟游戏

    自定义控件系列,前前后后分享了三四篇了,其实,在自定义控件的道路中,我们只仅仅迈出了一小步,未来的时间我们仍需走在路上,去探索那些未知的自定义领域.今天,是个周末的时刻,少些烦躁的代码,来一起实现一个 ...

  6. 前端笔记之Canvas

    一.Canvas基本使用 Canvas是HTML5的画布,Canvas算是"不务正业"的面向对象大总结,将面向对象玩极致. 算法为王!就是说canvas你不会,但是算法好,不怕写业 ...

  7. Unity入门之U2D——FlappyBird游戏制作

    首先新建项目,并下载资源 将资源移到Assets文件夹下 将Sprites里的BirdHero的Sprite Mode改为Multiple,因为这是多幅图 点击Sprite Editor,进行图片切割 ...

  8. canvas java 上传截图_在Vue项目中使用html2canvas生成页面截图并上传

    使用方法 项目中引入 npm install html2canvas html代码 //html代码 js代码 // 引入html2canvas import html2canvas from 'ht ...

  9. 画布Canvas的使用

    canvas.drawText();//画文本 canvas.drawArc();//画弧 canvas.drawCircle();//画圆 canvas.drawBitmap(); canvas.d ...

  10. Android 自定义View Canvas —— Bitmap

    Bitmap 绘制图片 常用的方法有一下几种 (1) drawBitmap(@NonNull Bitmap bitmap, float left, float top, @Nullable Paint ...

最新文章

  1. super返回不过来
  2. linux git hudson,如何使用SSH密钥配置Hudson和git插件
  3. Linux 之三 静态库及动态库的编写和使用
  4. java守护锁_Java 对象锁-synchronized()与线程的状态与生命周期与守护进程
  5. linux链接达梦数据库,linux下面 达梦数据库的JDBC链接
  6. 这些深度学习术语,你了解多少?(上)
  7. 微型计算机系统中 麦克风属于,模块1-2 计算机基础知识测验题目(50小题)
  8. 小米电视4A核心技术之语音识别浅析
  9. C++/C高级数据类型
  10. CentOS7连接无线网络
  11. 【Python】Time模块 ValueError: unconverted data remains: UnicodeEncodeError:
  12. 一种基于敏感度可调的语音情感识别方法及系统
  13. 过去的一切该翻篇了 好好奔向未来吧
  14. 母牛的故事 1243ACM实验题
  15. r语言dataellipse_R语言中的划分聚类模型
  16. [易飞]信息传递-多表(含外表)关联取值
  17. 关于使用Pytorch时,训练集模型表现很好但测试集模型表现极差的原因
  18. 迅雷链流量扶持放大招:手雷链克专区上线!
  19. 上升了百分之几怎么算_计算上涨百分比的公式,上涨比例怎么算公式?
  20. 青年歌手姚贝娜乳腺癌复发去世

热门文章

  1. cortex系列处理器排行_arm处理器排行_ARM Cortex A系列处理器性能分类比较ARM处理器排名 ZNDS资讯...
  2. [转贴]给想立志入行网络或已经初入行的朋友的建议(一)
  3. [BZOJ5145] [Ynoi2018] 五彩斑斓的世界 [并查集][分块][摊还分析]
  4. Oracle细节,plsql语法大全
  5. Layaair 3D场景使用
  6. Smartbi电子表格创建查询条件
  7. 左宗棠:大清朝最后一棵顶梁柱
  8. 案例分享:智邦科技上海办公室WLAN改造项目
  9. 手写个Tomcat雏型
  10. V4L2驱动的移植与应用(三)