【微信小游戏开发】小游戏敌机出现
英雄飞机也有了,子弹也有了,怎么可以少了飞机呢,对吧
同样,我们也不使用官方的图片,而是使用下面这张雪碧图
- 图片地址为: https://www.twle.cn/static/i/minigame/enemy.png
- 图片大小为
400x100
- 每个子弹大小为
100x100
下载这张图片,并保存到 images
目录
敌机一般都是从顶部出现的,然后一路飞到屏幕的下面
game.js
varc=wx.createCanvas();varctx=c.getContext('2d');
varbullet=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();
}
bullet.onload=function(){
reset(ctx);
ctx.drawImage(bullet,0,0,100,100,c.width/2-25,0,50,50);
draw_copy();
}
reset();
bullet.src='images/enemy.png'
虽然敌机大小为 100x100
,但我们把它绘制小一点,不然一屏幕都放不下几个敌机
运行效果如下
对敌机进行封装
因为剧情 (接下里的教程) 需要,我们对敌机做一些封装
functionEnemy(){
// 位置
this.x=0;
this.y=0;
//宽高
this.w=50;
this.h=50;
// 飞行速度
this.speed=2;
// 敌机图片
this.img=null;
// 敌机类型
this.kind=1;
// 原图位置
this.rx=0;
this.ry=0;
this.rw=100;
this.rh=100;
this.change_kind=function(k)
{
this.rx=(k-1)*100;
this.ry=0;
}
this.move=function(){
this.y+=this.speed;
};
this.draw=function(ctx){
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);
}
}
注意
- 我们绘制敌机的时候,
x
和y
所代表的,就是敌机中间的位置- 敌机的飞行方向是从下往上
是不是发现和子弹差不多,对的,等下我们会说
让敌机飞起来
把敌机放到动画里,敌机就会飞起来了
有一个点需要注意,敌机不可能凭空出现对吧,所以敌机初始化的 Y 坐标轴为 -h
然后我们就可以把敌机放到动画里,让敌机飞起来
varc=wx.createCanvas();varctx=c.getContext('2d');
varenemy=null;
functionEnemy()
{
//宽高
this.w=50;
this.h=50;
// 位置
this.x=0;
this.y=-this.h;
// 飞行速度
this.speed=2;
// 敌机图片
this.img=null;
// 敌机类型
this.kind=1;
// 原图位置
this.rx=0;
this.ry=0;
this.rw=100;
this.rh=100;
this.change_kind=function(k)
{
this.rx=(k-1)*100;
this.ry=0;
}
this.move=function(){
this.y+=this.speed;
};
this.draw=function(ctx){
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);
}
}
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);
enemy.move();
enemy.draw(ctx);
draw_copy();
requestAnimationFrame(animate_it);
}
enemy=newEnemy();
enemy.x=c.width/2;
enemy.y=-enemy.h;
enemy.img=wx.createImage();
enemy.img.onload=function(){
reset(ctx);
enemy.draw(ctx);
draw_copy();
requestAnimationFrame(animate_it);
}
reset();
enemy.img.src='images/enemy.png'
运行演示如下
更多敌机
我们每 800ms
产生一个敌机
这时候要使用一个数组来存储全部的敌机,还要检查敌机是否超出边界,如果超出了边界就删除敌机
注意,一般来说,敌机的产生速度要远远小于子弹的,不然子弹都忙不过来不是
还有一点,敌机的位置是随机的,所以我们要使用随机数创建一个敌机位置
game.js
varc=wx.createCanvas();varctx=c.getContext('2d');
varscreenHeight=c.height;
varscreenWidth=c.width;
functionEnemy(){
//宽高
this.w=50;
this.h=50;
// 位置
this.x=0;
this.y=-this.h;
// 飞行速度
this.speed=2;
// 敌机图片
this.img=null;
// 敌机类型
this.kind=1;
// 原图位置
this.rx=0;
this.ry=0;
this.rw=100;
this.rh=100;
this.change_kind=function(k){
this.rx=(k-1)*100;
this.ry=0;
}
this.move=function(){
this.y+=this.speed;
};
this.draw=function(ctx){
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);
}
}
varEnemys={
_data:[],
move:function(){
for(variinthis._data){
this._data[i].move();
if(this._data[i].y>=screenHeight){
this._data.splice(i,1);
}
}
},
add:function(enemy){
this._data.push(enemy);
},
draw:function(ctx){
for(variinthis._data){
this._data[i].draw(ctx);
}
}
}
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);
Enemys.move();
Enemys.draw(ctx);
draw_copy();
requestAnimationFrame(animate_it);
}
functioncreate_enemy(img){
varenemy=newEnemy();
enemy.x=(enemy.w/2)+Math.random()*(screenWidth-enemy.w/2);
enemy.y=-enemy.h;
enemy.img=img;
Enemys.add(enemy);
}
varenemy_img=wx.createImage();
enemy_img.onload=function(){
reset(ctx);
create_enemy(enemy_img);
Enemys.draw(ctx);
draw_copy();
setInterval(function(){create_enemy(enemy_img);},800);
requestAnimationFrame(animate_it);
}
reset();
enemy_img.src='images/enemy.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;
}
}
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();
}
}
}
}
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);
}
}
varBullet=inherits(Sprite);
Bullet.prototype.hit=function(){
returnthis.y<=0;
}
varEnemy=inherits(Sprite);
Enemy.prototype.hit=function(){
returnthis.y>=screenHeight;
}
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.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;
varbgm=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.img=img;
bullet.kind=1;
bullet.rw=60;
bullet.rh=60;
bullet.ctx=ctx;
Bucket.add(bullet,'buttet');
}
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.img=img;
enemy.kind=1;
enemy.rw=100;
enemy.rh=100;
enemy.ctx=ctx;
Bucket.add(enemy,'enemy');
}
functiontimeit(){
if(t%60==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.loaded(function(){
img=Resource.item('images/bg.jpg');
plane=Resource.item('images/plane.png');
start();
});
运行演示如下
手机录制视频会严重掉帧
以上是 【微信小游戏开发】小游戏敌机出现 的全部内容, 来源链接: utcz.com/a/129672.html