canvas小游戏指南
1.布局
绘制背景及图片按照实际图片大小绘制,比如
- 先获取图片的宽高
this.w = game.allImg["bg_day"].width;
this.h = game.allImg["bg_day"].height;
- 绘制背景,每一帧都需要向左移背景,让他动起来,当向左移动的时候右侧会露底,在这里多增加几张图片,当移动的x距离等于一屏宽的时候,让x = 0
game.draw.fillStyle = "#4ec0ca";
game.draw.fillRect(0, 0, game.canvas.width, game.canvas.height)
game.draw.drawImage(game.allImg["bg_day"], this.x, game.canvas.height - this.h)
game.draw.drawImage(game.allImg["bg_day"], this.x + this.w, game.canvas.height - this.h)
game.draw.drawImage(game.allImg["bg_day"], this.x + this.w * 2, game.canvas.height - this.h)
2.随机长度的管道
绘制随机长度管道,不仅感到高度要随机生成,绘制的时候 参数变为9个 drawImage(img,x1,y1,w1,h1,x2,y2,w2,h2)
- 第一个参数绘制的图片
- x1(图片裁剪的起始x坐标) y1(图片裁剪的起始y坐标) x2(图片绘制到画布的其实x坐标) y2(图片绘制到画布其实y坐标)
- w1,h1,w2,h2(图片宽高)
3.小鸟的飞行
小鸟与管道的碰撞检,当前一屏显示的管道都会存在数组中,因为管道是长度不等的,我们检测小鸟与每一条管道的碰撞
- B.x2 > = P.x1
- B.x1 < = P.x2
- B.y1 < = p.y1
- B.y2 > = this.space + P.y1
4. 场景管理
使用场景管理函数管理多个场景
- 全局中定义
scene
默认为 0 场景管理函数中,enter()
初始化场景属性 updateAndRender
更新和传染场景bindEvent
场景内的事件函数
enter(scene) {
switch (scene) {
case 0:
game.bg = new BackGround()
game.land = new Land()
this.titleW = game.allImg["title"].width;
this.titleX = game.canvas.width / 2 - this.titleW / 2;
this.titleY = -50;
this.btnX = game.canvas.width / 2 - game.allImg["button_play"].width / 2;
this.btnY = game.canvas.height;
this.birdX = game.canvas.width / 2 - game.allImg["bird0_0"].width / 2;
this.birdY = 220;
this.birdChangeY = 1;
break;
case 1:
game.scene = 1;
game.bg = new BackGround();
game.land = new Land();
this.tutorialW = game.allImg["tutorial"].width;
this.tutorialX = game.canvas.width / 2 - this.tutorialW / 2;
this.tutorialY = 250;
this.alpha = 1;
this.alphaChange = 0.03;
break;
...
updateAndRender(){
switch (game.scene){
case 0:
game.bg.render();
game.land.render();
this.titleY>=160?this.titleY=160:this.titleY+=5;
this.btnY<=370?this.btnY=370:this.btnY-=10;
if(this.birdY>300||this.birdY<220){
this.birdChangeY*=-1;
}
this.birdY+=this.birdChangeY;
game.draw.drawImage(game.allImg["title"],this.titleX,this.titleY);
game.draw.drawImage(game.allImg["bird0_0"],this.birdX,this.birdY);
game.draw.drawImage(game.allImg["button_play"],this.btnX,this.btnY);
break;
case 1:
game.bg.render();
game.land.render();
game.draw.drawImage(game.allImg["bird0_0"],game.canvas.width/2-24,160);
if(this.alpha>1||this.alpha<0)this.alphaChange*=-1;
this.alpha+=this.alphaChange;
game.draw.save();
game.draw.globalAlpha=this.alpha;
game.draw.drawImage(game.allImg["tutorial"],this.tutorialX,this.tutorialY);
game.draw.restore();
break;
...
bindEvent() {
game.canvas.onclick = (e) => {
switch (game.scene) {
case 0:
if (e.clientX >= this.btnX && e.clientX <= this.btnX + 116 && e.clientY >= this.btnY && e.clientX <= this.btnY + 70) {
this.enter(1)
}
break;
颁奖场景
每次用户结束游戏把分数存储
localStorage
中,有三个奖牌,数组中默认三个都为0,每次游戏结束后,获取当前localStorage
中的值,从大到下排序,如果当前值大于数组中第一个,赋值并状态为金牌,以此类推
let arr = JSON.parse(localStorage.getItem("FB"));
arr.sort(function (a,b) {
return b-a
})
for (let i = 0; i < arr.length; i++) {
if (game.score >= arr[0]) {
arr[0] = game.score;
this.model = "medals_1";
} else if (game.score >= arr[1]) {
this.model = "medals_2";
arr[1] = game.score;
} else if (game.score >= arr[2]) {
this.model = "medals_3";
arr[2] = game.score;
} else {
this.model = "medals_0"
}
}
this.best = arr[0];
localStorage.setItem("FB", JSON.stringify(arr));
绘制奖牌
game.draw.drawImage(game.allImg[this.model],this.panelX+28,this.panelY+44);
game.draw.fillStyle="#666"
game.draw.font="20px consolas";
game.draw.textAlign="right"
game.draw.fillText(game.score,(game.canvas.width / 2) + 90 , this.panelY + 50);
game.draw.fillText(this.best,(game.canvas.width / 2) + 90 , this.panelY + 96);