网页游戏Flappy Birds从0开始制作(七):初步完成游戏制作,可以开始游戏。
这一章则使一一加入场景元素,land,birds,Tunnel,sky,完成游戏初步demo.
第一步加入资源,即将用到上一章节的loadSource方法。
首先声明一个资源的对象数组并初始化数据:
var imglist = [
{ "name":"birds","src":"img/birds.png"},
{ "name":"land","src":"img/land.png"},
{ "name":"tunnel1","src":"img/pipe1.png"},
{ "name":"tunnel2","src":"img/pipe2.png"},
{ "name":"sky","src":"img/sky.png"}
];
然后就用上一章节的Loadresource方法完成实例化场景元素及开始游戏。
首先使实例化场景元素:通过imgs数组来获取资源文件。
load(imglist,function(imgs){
//实例化小鸟
var bird = new Bird(imgs["birds"],150,100,0.0003,0.0006,ctx);
//实例化天空
var sky1 = new Sky(imgs["sky"],0,-0.3,ctx);
var sky2 = new Sky(imgs["sky"],800,-0.3,ctx);
var land1 = new Land(imgs["land"],0,-0.3,ctx);//背景,X位置,速度,ctx
var land2 = new Land(imgs["land"],336*1,-0.3,ctx);
var land3 = new Land(imgs["land"],336*2,-0.3,ctx);
var land4 = new Land(imgs["land"],336*3,-0.3,ctx);
var tunnel1 = new Tunnel(imgs["tunnel2"],imgs["tunnel1"],400, -0.1,ctx);
var tunnel2 = new Tunnel(imgs["tunnel2"],imgs["tunnel1"],600, -0.1,ctx);
var tunnel3 = new Tunnel(imgs["tunnel2"],imgs["tunnel1"],800, -0.1,ctx);
var tunnel4 = new Tunnel(imgs["tunnel2"],imgs["tunnel1"],1000,-0.1,ctx);
var tunnel5 = new Tunnel(imgs["tunnel2"],imgs["tunnel1"],1200,-0.1,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.setNum(2);
land1.update(dt);
land1.draw();
land2.update(dt);
land2.draw();
land3.update(dt);
land3.draw();
land4.update(dt);
land4.draw();
land1.setNum(4);
tunnel1.update(dt);
tunnel1.draw();
tunnel2.update(dt);
tunnel2.draw();
tunnel3.update(dt);
tunnel3.draw();
tunnel4.update(dt);
tunnel4.draw();
tunnel5.update(dt);
tunnel5.draw();
tunnel1.setNum(5,200);
bird.update(dt);
bird.draw();
var gameover = false;
gameover = gameover || tunnel1.Collide(bird.x ,bird.y);
gameover = gameover || tunnel2.Collide(bird.x ,bird.y);
gameover = gameover || tunnel3.Collide(bird.x ,bird.y);
gameover = gameover || tunnel4.Collide(bird.x ,bird.y);
gameover = gameover || tunnel5.Collide(bird.x ,bird.y);
if(bird.y < 0 || bird.y > 488 -45/2 ){
gameover = true ;
}
if(!gameover){
requestAnimationFrame(run);
}
}
//每一帧都执行run函数
requestAnimationFrame(run);
//为canvas添加事件监听函数
canvas.addEventListener("click",function(){
bird.speed = -0.3;
} )
首先开一下设置时间,通过Data.now()获得当前时间,当开始游戏后没帧更新游戏,从而得出时间间隔,来更新各个场景元素在Canvas中的位置
var now = Date.now();
dt = now - preTime;
preTime = now;
是不是感觉有点像递归呢?
有了时间间隔则Draw出每个元素,并更新元素,达到滚动的效果。
if(bird.y < 0 || bird.y > 488 -45/2 ){
gameover = true ;
}
if(!gameover){
requestAnimationFrame(run);
}
这一段代码就是设置游戏是否结束的关键,如果小鸟的纵坐标小于0即与Canvas上方边界相撞或者大于488-45/2
即与land相撞,488使因为land背景高度为112px,canvas高度使600;所以600-112=488;-45/2即小鸟像素高度的一般。
游戏如果没结束就
requestAnimationFrame(run);
调用run函数,动态更新游戏,否则就不执行,游戏静止结束。
整个源码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>小游戏案例之Flappy Bird</title>
<link rel="stylesheet" href="style.css">
<script src="loadSource.js"></script>
<script src="birds.js"></script>
<script src="sky.js"></script>
<script src="land.js"></script>
<script src ="tunnel.js"></script>
</head>
<body>
<canvas class='myCanvas' id='myCanvas' width="800" height="600"></canvas>
</body>
<script>
var canvas=document.getElementById("myCanvas");
var ctx=canvas.getContext('2d');
var imglist = [
{ "name":"birds","src":"img/birds.png"},
{ "name":"land","src":"img/land.png"},
{ "name":"tunnel1","src":"img/pipe1.png"},
{ "name":"tunnel2","src":"img/pipe2.png"},
{ "name":"sky","src":"img/sky.png"}
];
load(imglist,function(imgs){
//实例化小鸟
var bird = new Bird(imgs["birds"],150,100,0.0003,0.0006,ctx);
//实例化天空
var sky1 = new Sky(imgs["sky"],0,-0.3,ctx);
var sky2 = new Sky(imgs["sky"],800,-0.3,ctx);
var land1 = new Land(imgs["land"],0,-0.3,ctx);//背景,X位置,速度,ctx
var land2 = new Land(imgs["land"],336*1,-0.3,ctx);
var land3 = new Land(imgs["land"],336*2,-0.3,ctx);
var land4 = new Land(imgs["land"],336*3,-0.3,ctx);
var tunnel1 = new Tunnel(imgs["tunnel2"],imgs["tunnel1"],400, -0.1,ctx);
var tunnel2 = new Tunnel(imgs["tunnel2"],imgs["tunnel1"],600, -0.1,ctx);
var tunnel3 = new Tunnel(imgs["tunnel2"],imgs["tunnel1"],800, -0.1,ctx);
var tunnel4 = new Tunnel(imgs["tunnel2"],imgs["tunnel1"],1000,-0.1,ctx);
var tunnel5 = new Tunnel(imgs["tunnel2"],imgs["tunnel1"],1200,-0.1,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.setNum(2);
land1.update(dt);
land1.draw();
land2.update(dt);
land2.draw();
land3.update(dt);
land3.draw();
land4.update(dt);
land4.draw();
land1.setNum(4);
tunnel1.update(dt);
tunnel1.draw();
tunnel2.update(dt);
tunnel2.draw();
tunnel3.update(dt);
tunnel3.draw();
tunnel4.update(dt);
tunnel4.draw();
tunnel5.update(dt);
tunnel5.draw();
tunnel1.setNum(5,200);
bird.update(dt);
bird.draw();
var gameover = false;
gameover = gameover || tunnel1.Collide(bird.x ,bird.y);
gameover = gameover || tunnel2.Collide(bird.x ,bird.y);
gameover = gameover || tunnel3.Collide(bird.x ,bird.y);
gameover = gameover || tunnel4.Collide(bird.x ,bird.y);
gameover = gameover || tunnel5.Collide(bird.x ,bird.y);
if(bird.y < 0 || bird.y > 488 -45/2 ){
gameover = true ;
}
if(!gameover){
requestAnimationFrame(run);
}
}
//每一帧都执行run函数
requestAnimationFrame(run);
//为canvas添加事件监听函数
canvas.addEventListener("click",function(){
bird.speed = -0.3;
} )
})
</script>
</html>