【微信小游戏开发】小游戏敌机爆炸效果 - 雪碧图动画效果

敌机被消灭了怎么可能没有爆炸效果呢?对吧

接下来这章节我们就来做一个爆炸效果

同样,我们也不使用官方的图片,而是使用下面这张雪碧图

【微信小游戏开发】小游戏敌机爆炸效果 - 雪碧图动画效果

  1. 图片地址为: https://www.twle.cn/static/i/minigame/boom.png

  2. 图片大小为 300x100

  3. 每个子弹大小为 100x100

下载这张图片,并保存到 images 目录

【微信小游戏开发】小游戏敌机爆炸效果 - 雪碧图动画效果

爆炸效果出现点不决定,一般出现于被消灭的敌机附近

所以我们随便来一个点

game.js

varc=wx.createCanvas();

varctx=c.getContext('2d');

varboom=wx.createImage();

functionreset(){

ctx.save();

ctx.fillStyle="#fff";

ctx.fillRect(0,0,c.width,c.height);

ctx.restore();

}

functiondraw_copy(){

ctx.save();

ctx.textAlign="center"// 居中对齐

ctx.textBaseline="middle"//垂直居中绘制

ctx.fillStyle="#aaa";

ctx.font="16px Arial"// 字体大小 16 像素

ctx.fillText("简单教程,简单编程",c.width/2,(c.height-108))

ctx.fillText(" © 2015-2018 www.twle.cn",c.width/2,(c.height-128));

ctx.restore();

}

boom.onload=function(){

reset(ctx);

ctx.drawImage(boom,0,0,100,100,c.width/2-25,100,50,50);

draw_copy();

}

reset();

boom.src='images/boom.png';

虽然爆炸图片大小为 100x100 ,但我们把它绘制小一点,不然爆炸效果会闪到其它的敌机

运行效果如下

【微信小游戏开发】小游戏敌机爆炸效果 - 雪碧图动画效果

让爆炸动画显示出来

我们每 300ms 更新一次图片,更新图片很简单就是简单的移动 drawImage() 中的截图位置

game.js

varc=wx.createCanvas();

varctx=c.getContext('2d');

varboom=wx.createImage();

functionreset(){

ctx.save();

ctx.fillStyle="#fff";

ctx.fillRect(0,0,c.width,c.height);

ctx.restore();

}

functiondraw_copy(){

ctx.save();

ctx.textAlign="center"// 居中对齐

ctx.textBaseline="middle"//垂直居中绘制

ctx.fillStyle="#aaa";

ctx.font="16px Arial"// 字体大小 16 像素

ctx.fillText("简单教程,简单编程",c.width/2,(c.height-108))

ctx.fillText(" © 2015-2018 www.twle.cn",c.width/2,(c.height-128));

ctx.restore();

}

vari=0;

functiondraw_boom(){

reset(ctx);

ctx.drawImage(boom,i*100,0,100,100,c.width/2-25,100,50,50);

i++;

if(i==3)

i=0

}

boom.onload=function(){

draw_boom();

setInterval(function(){draw_boom();},200);

draw_copy();

}

reset();

boom.src='images/boom.png'

运行演示如下

对爆炸效果进行封装

首先,爆炸效果的点是不会移动的,当显示完最后一张图片,爆炸效果就要消失

functionBoom(){

// 位置

this.x=0;

this.y=0;

//宽高

this.w=50;

this.h=50;

// 爆炸程度

this.speed=0;

// 图片

this.img=null;

this.ctx=null;

this.img_size=3;

// 类型

this.kind=1;

// 原图位置

this.rx=0;

this.ry=0;

this.rw=100;

this.rh=100;

this.change_kind=function(){

this.kind++;

this.rx=(this.kind-1)*this.rw;

this.ry=0;

}

this.move=function(){

this.speed++;

if(this.speed%20==0)

this.change_kind();

};

this.draw=function(){

this.ctx.drawImage(this.img,this.rx,this.ry,

this.rw,this.rh,

this.x-this.w/2,this.y-this.h/2,

this.w,this.h);

}

this.hit=function(){

returnthis.kind==this.img_size;

}

}

对这个封装是不是很熟悉,对的,其实所有的图形动画都是大同小异

我们写一个范例演示下封装后的效果

game.js

functionBoom(){

// 位置

this.x=0;

this.y=0;

//宽高

this.w=50;

this.h=50;

// 爆炸程度

this.speed=0;

// 图片

this.img=null;

this.ctx=null;

this.img_size=3;

// 类型

this.kind=1;

// 原图位置

this.rx=0;

this.ry=0;

this.rw=100;

this.rh=100;

this.change_kind=function(){

this.kind++;

this.rx=(this.kind-1)*this.rw;

this.ry=0;

}

this.move=function(){

this.speed++;

if(this.speed%20==0)

this.change_kind();

};

this.draw=function(){

this.ctx.drawImage(this.img,this.rx,this.ry,

this.rw,this.rh,

this.x-this.w/2,this.y-this.h/2,

this.w,this.h);

}

this.hit=function(){

returnthis.kind==this.img_size;

}

}

varc=wx.createCanvas();

varctx=c.getContext('2d');

varbuckets=[];

functionreset(){

ctx.save();

ctx.fillStyle="#fff";

ctx.fillRect(0,0,c.width,c.height);

ctx.restore();

}

functiondraw_copy(){

ctx.save();

ctx.textAlign="center"// 居中对齐

ctx.textBaseline="middle"//垂直居中绘制

ctx.fillStyle="#aaa";

ctx.font="16px Arial"// 字体大小 16 像素

ctx.fillText("简单教程,简单编程",c.width/2,(c.height-108))

ctx.fillText(" © 2015-2018 www.twle.cn",c.width/2,(c.height-128));

ctx.restore();

}

functionanimate_it(){

reset(ctx);

for(variinbuckets){

buckets[i].move();

if(buckets[i].hit()){

buckets.splice(i,1);

continue;

}

buckets[i].draw(ctx);

}

draw_copy();

requestAnimationFrame(animate_it);

}

functioncreate_boom(img){

varboom=newBoom();

boom.x=Math.random()*c.width;

boom.y=Math.random()*c.height;

boom.ctx=ctx;

boom.img=img;

buckets.push(boom);

}

varboom=wx.createImage();

boom.onload=function(){

create_boom(boom);

requestAnimationFrame(animate_it);

setInterval(function(){create_boom(boom);},1000);

}

reset();

boom.src='images/boom.png'

运行演示如下

把爆炸效果加到被命中的飞机上

我们把刚刚爆炸的效果加到被命中的飞机上

这里有一个要点,如果飞机被命中,那么这个飞机就要被销毁,然后用一个新的爆炸效果代替原来的位置

对的,就是这么简单

game.js

varinherits=function(superCtor){

varf=function(){superCtor.call(this);}

f.super_=superCtor;

f.prototype=Object.create(superCtor.prototype,{

constructor:{

value:f,

enumerable:false,

writable:true,

configurable:true

}

});

returnf;

};

varResource={

_res:[],// [][] 资源对象数组, 0 表示资源 1 url 2 类型 3 是否加载完成

_load:function(idx,ops){

varres=this._res[idx];

if(!res[3]){

if(res[2]=="audio")

this._load_audio(res[1],idx,ops)

if(res[2]=="image")

this._load_image(res[1],idx,ops);

}

},

_load_image:function(src,i,ops){

varimg=wx.createImage();

varthat=this;

that._res[i][0]=img;

img.onload=function(){

that._res[i][3]=true;

}

img.src=src;

},

_load_audio:function(src,i,ops){

varaudio=wx.createInnerAudioContext();

if(ops!=null){

for(varkinops){

audio[k]=ops[k];

}

}

varthat=this;

that._res[i][0]=audio;

audio.onCanplay(function(){

that._res[i][3]=true;

});

audio.src=src;

},

loaded:function(callback){

for(vari=0;i<this._res.length;i++){

if(!this._res[i][3]){

varthat=this;

setTimeout(function(){that.loaded(callback);},200);

return;

}

}

callback();

},

add:function(src,type,id,ops){

this._res.push([null,src,type,false,id]);

this._load(this._res.length-1,ops);

},

item:function(src){

for(vari=0;i<this._res.length;i++){

if(this._res[i][1]==src){

returnthis._res[i][0];

}

}

returnnull;

}

}

functionSprite(){

// 位置

this.x=0;

this.y=0;

//宽高

this.w=0;

this.h=0;

// 飞行速度

this.speed=0;

// 图片

this.img=null;

// 类型

this.kind=0;

// 原图位置

this.rx=0;

this.ry=0;

this.rw=0;

this.rh=0;

this.ctx=null;

this.change_kind=function(k){

this.rx=(k-1)*this.rw;

this.ry=0;

}

this.move=function(){

this.y+=this.speed;

};

this.draw=function(){

this.ctx.drawImage(this.img,this.rx,this.ry,

this.rw,this.rh,

this.x-this.w/2,this.y-this.h/2,

this.w,this.h);

}

}

varBucket={

_bucket:{},

move:function(){

for(variinthis._bucket){

for(varjinthis._bucket[i]){

this._bucket[i][j].move();

if(this._bucket[i][j].hit()){

this._bucket[i].splice(j,1);

}

}

}

},

add:function(obj,bucket){

if(!(bucketinthis._bucket)){

this._bucket[bucket]=[];

}

this._bucket[bucket].push(obj);

},

draw:function(ctx){

for(variinthis._bucket){

for(varjinthis._bucket[i]){

this._bucket[i][j].draw();

}

}

},

enemy_hit:function(){

varenemys=this._bucket['enemy'];

varbullets=this._bucket['bullet'];

for(variinenemys){

varenemy=enemys[i];

for(varjinbullets){

varbullet=bullets[j];

varr=enemy.w/2;

varx=(bullet.x-enemy.x);

vary=(bullet.y-enemy.y);

// 因为子弹比敌机要小,所以直接判断子弹是否和敌机相交即可

if(x*x+y*y<=r*r){

// 创建爆炸效果

create_boom(enemy.x,enemy.y);

// 移除子弹

this._bucket['bullet'].splice(j,1);

// 移除飞机

this._bucket['enemy'].splice(i,1);

}

}

}

}

}

functionSprite(){

// 位置

this.x=0;

this.y=0;

//宽高

this.w=0;

this.h=0;

// 飞行速度

this.speed=0;

// 图片

this.img=null;

// 类型

this.kind=0;

// 原图位置

this.rx=0;

this.ry=0;

this.rw=0;

this.rh=0;

this.ctx=null;

this.draw=function(){

this.ctx.drawImage(this.img,this.rx,this.ry,

this.rw,this.rh,

this.x-this.w/2,this.y-this.h/2,

this.w,this.h);

}

}

varBullet=inherits(Sprite);

Bullet.prototype.hit=function(){

returnthis.y<=0;

}

Bullet.prototype.move=function(){

this.y+=this.speed;

};

varEnemy=inherits(Sprite);

Enemy.prototype.hit=function(){

returnthis.y>=screenHeight;

}

Enemy.prototype.move=function(){

this.y+=this.speed;

};

varBoom=inherits(Sprite);

Boom.prototype.img_size=3;

Boom.prototype.change_kind=function(){

this.kind++;

this.rx=(this.kind-1)*this.rw;

this.ry=0;

}

Boom.prototype.move=function(){

this.speed++;

if(this.speed%20==0)

this.change_kind();

};

Boom.prototype.hit=function(){

returnthis.kind==this.img_size;

}

varc=wx.createCanvas();

varctx=c.getContext('2d');

varimg=wx.createImage();

varplane=wx.createImage();

varbgCanvas=null;

varoffset=0;

varw=0;

varh=0;

varscreenWidth=c.width;

varscreenHeight=c.height;

// 上一次飞机的位置

varlasted={x:0,y:0};

// 触摸区域是否在飞机内部

varin_plane=false;

// 创建计时器

vart=0;

functioninit_bg(){

bgCanvas=wx.createCanvas();

bgCanvas.width=screenWidth;

bgCanvas.height=screenHeight+h;

varbgctx=bgCanvas.getContext('2d');

vary=0;

varx=0;

// 底部多绘制一张图片

while(y<screenHeight+h){

x=0;

while(x<screenWidth){

bgctx.drawImage(img,x,y,w,h);

x+=w;

}

y+=h;

}

}

functionreset(){

ctx.save();

ctx.fillStyle="#fff";

ctx.fillRect(0,0,c.width,c.height);

ctx.restore();

}

functiondraw_copy(){

ctx.save();

ctx.textAlign="center"// 居中对齐

ctx.textBaseline="middle"//垂直居中绘制

ctx.fillStyle="#aaa";

ctx.font="16px Arial"// 字体大小 16 像素

ctx.fillText("简单教程,简单编程",c.width/2,(c.height-36))

ctx.fillText(" © 2015-2018 www.twle.cn",c.width/2,(c.height-18));

ctx.restore();

}

functionanimate_it(){

reset(ctx);

ctx.drawImage(bgCanvas,0,offset,screenWidth,screenHeight,0,0,screenWidth,screenHeight);

Bucket.move();

Bucket.enemy_hit();

Bucket.draw(ctx);

ctx.drawImage(plane,0,0,128,128,lasted.x-64,lasted.y-64,128,128);

draw_copy();

timeit();

offset;

if(offset%h==0){

offset=0;

}

requestAnimationFrame(animate_it);

}

wx.onShow(function(){

Resource.item('audio/bgm.mp3').play();

})

wx.onAudioInterruptionBegin(function(){

// 暂停音乐

Resource.item('audio/bgm.mp3').stop();

// 中断动画

//cancelAnimationFrame(animate_it);

})

wx.onAudioInterruptionEnd(function(){

Resource.item('audio/bgm.mp3').play()

// 恢复动画

cancelAnimationFrame(animate_it);

})

wx.onTouchStart(function(e){

varx=e.touches[0].clientX;

vary=e.touches[0].clientY;

if(plane_hit(x,y)){

in_plane=true;

}

});

wx.onTouchEnd(function(e){

if(in_plane){

lasted.x=e.touches[0].clientX;

lasted.y=e.touches[0].clientY;

in_plane=false;

}

});

// 触摸移动事件

wx.onTouchMove(function(e){

if(in_plane){

lasted.x=e.touches[0].clientX;

lasted.y=e.touches[0].clientY;

}

})

functionplane_hit(x,y){

returnx>(lasted.x-64)&&

x<(lasted.x+64)&&

y>(lasted.y-64)&&

y<(lasted.y+64);

}

functionstart(){

w=screenWidth>img.width?img.width:screenWidth;

h=img.height*(w/img.width);

lasted.x=(screenWidth-128)/2;

lasted.y=screenHeight-128;

Resource.item('audio/bgm.mp3').play();

init_bg();

ctx.drawImage(plane,0,0,128,128,lasted.x,lasted.y,128,128);

draw_copy();

requestAnimationFrame(animate_it);

}

functioncreate_bullet(img){

varbullet=newBullet();

bullet.x=lasted.x;

bullet.y=lasted.y;

bullet.img=img;

bullet.w=30;

bullet.h=30;

bullet.speed=-2;

bullet.kind=1;

bullet.rw=60;

bullet.rh=60;

bullet.ctx=ctx;

Bucket.add(bullet,'bullet');

}

functioncreate_enemy(img){

varenemy=newEnemy();

enemy.w=50;

enemy.h=50;

enemy.x=(enemy.w/2)+Math.random()*(screenWidth-enemy.w/2);

enemy.y=-50;

enemy.img=img;

enemy.speed=2;

enemy.kind=1;

enemy.rw=100;

enemy.rh=100;

enemy.ctx=ctx;

Bucket.add(enemy,'enemy');

}

functioncreate_boom(x,y){

varboom=newBoom();

boom.w=50;

boom.h=50;

boom.x=x;

boom.y=y;

boom.img=Resource.item('images/boom.png');

boom.speed=0;

boom.kind=1;

boom.rw=100;

boom.rh=100;

boom.ctx=ctx;

Bucket.add(boom,'boom');

}

functiontimeit(){

if(t%30==0){

varenemy=Resource.item('images/enemy.png');

create_enemy(enemy);

}

if(in_plane&&t%20==0){

varbullet=Resource.item('images/bullet.png');

create_bullet(bullet);

}

t++;

}

reset();

Resource.add('images/bg.jpg','image');

Resource.add('audio/bgm.mp3','audio',null,{loop:true});

Resource.add('images/plane.png','image');

Resource.add('images/bullet.png','image');

Resource.add('images/enemy.png','image');

Resource.add('images/boom.png','image');

Resource.loaded(function(){

img=Resource.item('images/bg.jpg');

plane=Resource.item('images/plane.png');

start();

});

运行演示如下

以上是 【微信小游戏开发】小游戏敌机爆炸效果 - 雪碧图动画效果 的全部内容, 来源链接: utcz.com/a/129605.html

回到顶部