这篇文章我们来讲一讲用canvas画一个躲水果的小游戏。就是通过手指控制一个人物移动来躲避水果,若发生碰撞,则游戏结束。
我们定义一个game_control对象来处理初始化,事件绑定,游戏开始,游戏结果判定,游戏结束等判定。
在游戏中,我们需要一个人物以及三种水果的图片,我们做成了雪碧图。
接下来直接上代码吧~
首先我们定义一个ship对象,3个水果、一个人物都是基于这个对象的。
function ship(options){
if (options) {
var width=options.width,
height=options.height;
this.x=options.x;
this.y=options.y;
this.width=width;
this.height=height;
this.first_x=options.x;
this.first_y=options.y;
this.speedx=options.speedx;
this.speedy=options.speedy;
this.csspeedx=options.speedx;
this.csspeedy=options.speedy;
this.xDirection=options.xDirection||1;//x轴方向
this.yDirection=options.yDirection||1;//y轴方向
var canvasOffscreen = document.createElement('canvas');
canvasOffscreen.width =width;
canvasOffscreen.height =height;
canvasOffscreen.getContext('2d').drawImage(options.image, options.sourcex, options.sourcey, options.sourcewidth, options.sourceheight, 0, 0, width, height);
this.canvasOffscreen=canvasOffscreen;
this.init();
}
}
ship.prototype={
init:function(){
},
reset:function(){
},
draw:function(ctx){
//let canvasOffscreen=this.canvasOffscreen;
ctx.drawImage(this.canvasOffscreen, this.x, this.y);
},
move:function(modifier){
this.x+=this.xDirection*this.speedx * modifier;
this.y+=this.yDirection*this.speedy * modifier;
if(this.x>winwidth-this.width){
this.x=winwidth-this.width;
this.xDirection=-1;
}else if(this.x<0){
this.x=0;
this.xDirection=1
}
if(this.y>winheight-this.height){
this.y=winheight-this.height;
this.yDirection=-1;
}else if(this.y<0){
this.y=0;
this.yDirection=1;
}
}
}
当我们用canvas绘制人物和水果时,可以采用离屏绘制的方法,就是先将每个水果,人物绘制一遍,然后每次重绘的时候,再用canvas将这个已绘制的绘制出来就可以了,这样效率会比每次都直接绘制图片要高
var canvasOffscreen = document.createElement('canvas');
canvasOffscreen.width =width;
canvasOffscreen.height =height;
canvasOffscreen.getContext('2d').drawImage(options.image, options.sourcex, options.sourcey, options.sourcewidth, options.sourceheight, 0, 0, width, height);
ctx.drawImage(this.canvasOffscreen, this.x, this.y);
接下来说一下game_control 初始化init方法吧
init:function(){
var canvas=document.getElementById('game-canvas'),
self=this,
ctx=canvas.getContext('2d');
self.ctx=ctx;
canvas.width=winwidth;
canvas.height=winheight;
let img=new Image();
img.οnlοad=function(){
var zjb=new hero({
image:img,
x:gettruesize(250),
y:gettruesize(56),
width:gettruesize(50),
height:gettruesize(50),
sourcewidth:104,
sourceheight:104,
sourcex:0,
sourcey:0
});
for(var i=0;i<3;i++){
var x=60,y=110;
if(i==1){x=38,y=330;}
if(i==2){x=218,y=338;}
var monster=new ship({
image:img,
x:gettruesize(x),
y:gettruesize(y),
width:gettruesize(50),
height:gettruesize(50),
sourcewidth:104,
sourceheight:104,
speedx:gettruesize(getrandom(60,100)),
speedy:gettruesize(getrandom(60,100)),
sourcex:104*(i+1),
sourcey:0
});
self.monsters.push(monster);
}
self.objs=zjb;
self.draw();
self.bindmove(canvas,zjb);
}
img.src="all.png";
}
主要作用是当 雪碧图载入完成后,定义出一个人物对象以及3个水果对象,并通过draw方法将他们用canvas绘制出来,同时给人物对象进行手指事件的绑定(bindmove方法)
接下来讲讲bindmove方法
bindmove:function(canvas,hero){
let self=this;
canvas.addEventListener('touchstart', function(e) {
var event = e||window.event,
csx = event.touches[0].clientX,
csy = event.touches[0].clientY,
nanshengcsx = hero.x,
nanshengcsy = hero.y;
if (csx <= hero.x + hero.width && csx >= hero.x && csy <= hero.y + hero.height && csy >= hero.y) {
if (!self.startstate) {
self.start();
timer = setInterval(function(){
self.draw();
}, 1);
}
document.addEventListener('touchmove', move,false);
function move(e){
e.preventDefault();
var event = e||window.event,
nowx = event.touches[0].clientX,
nowy = event.touches[0].clientY;
hero.x = nanshengcsx + nowx - csx;
hero.y = nanshengcsy + nowy - csy;
if(hero.x<0){
hero.x=0;
}else if(hero.x+hero.width>winwidth){
hero.x=winwidth-hero.width;
}
if(hero.y<0){
hero.y=0;
}else if(hero.y+hero.height>winheight){
hero.y=winheight-hero.height;
}
}
function moveend(e){
document.removeEventListener('touchend',moveend);
document.removeEventListener('touchmove',move);
}
document.addEventListener('touchend', moveend ,false);
}
},false);
}
这个方法用来判断手指触碰屏幕时是否在 人物这个位置,如果是,则游戏开始(触发start方法),并注册移动事件,跟随手指移动而移动。
start方法中定义一个循环,让canvas 一帧一帧的画。
start:function(){
var self=this;
this.startstate=true;
this.then=Date.now();
this.starttime=this.then;
document.getElementById('tips').style.display="none";
timer = setInterval(function(){
self.draw();
}, 1);
}
最后还要一个check方法,来判断人物与水果间有没有发生触碰,若有则游戏结束。
check:function(){
var last=this.then-this.starttime;
var monsters=this.monsters;
var nansheng=this.objs;
if (this.monsterSum != Math.floor(last / 5000)){//如果时间经过5秒就增加一个怪兽实例
this.monsterSum ++;
for(var i=0;i<monsters.length;i++){
monsters[i].speedx+=60;
monsters[i].speedy+=60;
}
}
for(var i=0;i<monsters.length;i++){
var monster1=monsters[i];
if ((monster1.x - nansheng.width) <= nansheng.x && nansheng.x <= (monster1.x + monster1.width) && (monster1.y - nansheng.height) <= nansheng.y && nansheng.y <= (monster1.y + monster1.height)) {
this.end();
}
}
}
这样一个简单的小游戏就完成啦~