效果圖:
實作思路
1.首先實作一個雷達效果,參考前面的文章(https://blog.csdn.net/dkm123456/article/details/114312198);
2.點選掃描按鈕,雷達旋轉、同時建立敵機對象,并讓敵機運動起來;
3.點選鎖定按鈕,會在敵機的位置建立鎖定的圖形,達到鎖定的效果(因為雷達和飛彈都用了小尾巴效果,是以鎖定目标就用了一個新畫布);
4.點選發射按鈕,建立飛彈對象,飛彈根據敵機的位置,不停的調整位置,向目标運動,當到達目标一定範圍就判定為命中目标;
5.命中目标後産生爆炸效果,并彈出目标已摧毀,同時清除相關對象,比如飛彈、敵機、鎖定對象等。
建立敵機對象(雷達上運動的小球)
構造函數(圓或者叫球)
//構造函數
function Ball(o){
this.x=0,//圓心X坐标
this.y=0,//圓心Y坐标
this.r=0,//半徑
this.startAngle=0,//開始角度
this.endAngle=0,//結束角度
this.anticlockwise=false;//順時針,逆時針方向指定
this.stroke=false;//是否描邊
this.fill=false;//是否填充
this.scaleX=1;//縮放X比例
this.scaleY=1;//縮放Y比例
this.rotate=0;
this.init(o);
}
//初始化
Ball.prototype.init=function(o){
for(var key in o){
this[key]=o[key];
}
}
//繪制
Ball.prototype.render=function(context){
var ctx=context;//擷取上下文
ctx.save();
ctx.beginPath();
ctx.translate(this.x,this.y);
if(this.fill){
ctx.moveTo(0,0);
}
//ctx.moveTo(this.x,this.y);
ctx.scale(this.scaleX,this.scaleY);//設定縮放
ctx.arc(0,0,this.r,this.startAngle,this.endAngle);//畫圓
if(this.lineWidth){//線寬
ctx.lineWidth=this.lineWidth;
}
if(this.fill){//是否填充
this.fillStyle?(ctx.fillStyle=this.fillStyle):null;
ctx.fill();
}
if(this.stroke){//是否描邊
this.strokeStyle?(ctx.strokeStyle=this.strokeStyle):null;
ctx.stroke();
}
ctx.restore();
return this;
}
建立
//建立敵機
Radar.prototype.addEnemy=function(){
//繪制敵機
var enemy = new Ball({
//x:0,y:0,
x:_.getRandom(30,450),//圓心X坐标
y:_.getRandom(30,450),//圓心X坐标
r:3,//半徑
startAngle:0,//開始角度
endAngle:2*Math.PI,//結束角度
fill:true,//是否填充
fillStyle:'red'//填充的樣式
})
this.renderArr.push(enemy);
this.enemy=enemy;
}
加入運動
if(!this.anglePi){
this.anglePi=Math.atan2(enemy.y-250,enemy.x-250);
}
console.log(this.anglePi)
var dis=1;
if(this.anglePi<1/2*Math.PI && this.anglePi>0){//0度-90度
dis=-1;
}else if(this.anglePi<-1/2*Math.PI && this.anglePi>-Math.PI){//-180度-90度
dis=-1;
}else if(this.anglePi>-1/2*Math.PI && this.anglePi<0){//-90度-0度
dis=-1;
}else{//90度-180度
dis=1;
}
var disX=Math.cos(this.anglePi)*this.enemySpeed*dis;
var disY=Math.sin(this.anglePi)*this.enemySpeed*dis;
//更新敵機的位置
enemy.x+=disX;
enemy.y+=disY;
效果
鎖定(繪制幾個圓和幾個線段來訓示被鎖定)
//鎖定目标(繪制幾個圓和幾個線段來訓示被鎖定)
Radar.prototype.aimWeapon=function() {
var aimWeaponDest = this.aimWeaponDest;
if(aimWeaponDest && aimWeaponDest.length>0){
return ;
}
var enemy = this.enemy;
if(!enemy) return ;
var aimWeaponDestArr=[];
//根據敵機來建立一個圓
var aimWeapon = new Ball({
x:enemy.x,//圓心X坐标
y:enemy.y,//圓心X坐标
r:6,//半徑
startAngle:0,//開始角度
endAngle:2*Math.PI,//結束角度
stroke:true,//是否描邊
strokeStyle:'red'//樣式
})
this.renderArr2.push(aimWeapon);
aimWeaponDestArr.push(aimWeapon);
aimWeapon = new Ball({
x:enemy.x,//圓心X坐标
y:enemy.y,//圓心X坐标
r:8,//半徑
startAngle:0,//開始角度
endAngle:2*Math.PI,//結束角度
stroke:true,//是否描邊
strokeStyle:'red'//樣式
})
this.renderArr2.push(aimWeapon);
aimWeaponDestArr.push(aimWeapon);
aimWeapon = new Ball({
x:enemy.x,//圓心X坐标
y:enemy.y,//圓心X坐标
r:10,//半徑
startAngle:0,//開始角度
endAngle:2*Math.PI,//結束角度
stroke:true,//是否描邊
strokeStyle:'red'//樣式
})
this.renderArr2.push(aimWeapon);
aimWeaponDestArr.push(aimWeapon);
aimWeapon = new Ball({
x:enemy.x,//圓心X坐标
y:enemy.y,//圓心X坐标
r:12,//半徑
startAngle:0,//開始角度
endAngle:2*Math.PI,//結束角度
stroke:true,//是否描邊
strokeStyle:'red'//樣式
})
this.renderArr2.push(aimWeapon);
aimWeaponDestArr.push(aimWeapon);
var line = new Line({
x:enemy.x,
y:enemy.y,
startX:0,
startY:0,
endX:0,
endY:20,
strokeStyle:'red',
thin:true
})
this.renderArr2.push(line);
aimWeaponDestArr.push(line);
line = new Line({
x:enemy.x,
y:enemy.y,
startX:0,
startY:0,
endX:0,
endY:-20,
strokeStyle:'red',
thin:true
})
this.renderArr2.push(line);
aimWeaponDestArr.push(line);
line = new Line({
x:enemy.x,
y:enemy.y,
startX:0,
startY:0,
endX:20,
endY:0,
strokeStyle:'red',
thin:true
})
this.renderArr2.push(line);
aimWeaponDestArr.push(line);
line = new Line({
x:enemy.x,
y:enemy.y,
startX:0,
startY:0,
endX:-20,
endY:0,
strokeStyle:'red',
thin:true
})
this.renderArr2.push(line);
aimWeaponDestArr.push(line);
this.aimWeaponDest = aimWeaponDestArr;
}
這裡用了新的畫布(兩個畫布重合在一起)
var canvas2 = document.createElement('canvas');//建立畫布
canvas2.style.cssText="position:absolute;left:0px;";//設定樣式
canvas2.width = W; //設定寬度
canvas2.height = H;//設定高度
el.appendChild(canvas2);//添加到指定的dom對象中
this.ctx2 = canvas2.getContext('2d');
this.canvas2=canvas2;
跟随敵機運動,同時在旋轉
//鎖定目标跟随敵機
var aimWeaponDest = this.aimWeaponDest;
if(aimWeaponDest && aimWeaponDest.length>0){
aimWeaponDest.forEach(function(item){
//鎖定圖形裡面的每個對象xy都跟着變化
item.x+=disX;
item.y+=disY;
//同時在旋轉
item.rotate+=0.01*Math.PI;
if(item.rotate>=2*Math.PI){
item.rotate=0;
}
})
}
效果
發射飛彈
//發射飛彈
Radar.prototype.launch=function() {
if(!this.aimWeaponDest || this.aimWeaponDest.length<=0) return ;//沒有鎖定就不操作
if(this.missile) return ;
var missile = new Ball({
x:250,//圓心X坐标
y:500,//圓心X坐标
r:2,//半徑
startAngle:0,//開始角度
endAngle:2*Math.PI,//結束角度
fill:true,//是否填充
fillStyle:'white'//樣式
})
this.renderArr.push(missile);
this.missile=missile;
}
飛彈根據目标的位置,不停的調整自己的方向
//如果有飛彈、飛彈朝目标飛行
var missile=this.missile;
if(missile){
//根據飛彈和敵機 的位置來計算方向
var s = this.missileSpeed;
var mDis=1;
var anglePi2=Math.atan2(missile.y-enemy.y,missile.x-enemy.x);
if(missile.y-enemy.y<10 && missile.x-enemy.x<10){//判定為擊中目标
this.destroy();
return ;
}
if(anglePi2>1/2*Math.PI && anglePi2<Math.PI){//90度- 180度
mDis=-1;
}else if(anglePi2>-1/2*Math.PI && anglePi2<0){//-90度-0度
mDis=-1;
}else if(anglePi2>0 && anglePi2<1/2*Math.PI){//0度-90度
mDis=-1;
}else if(anglePi2>-Math.PI && anglePi2<-1/2*Math.PI){//-180度 - -90度
mDis=1;
}
var mdisX=Math.cos(anglePi2)*s*mDis;
var mdisY=Math.sin(anglePi2)*s*mDis;
//更新飛彈的位置
missile.x+=mdisX;
missile.y+=mdisY;
}
當飛彈與目标接近到一定位置時就判定為命中(摧毀目标)
//目标摧毀、自動消耗
Radar.prototype.destroy=function(type) {
//如果type則表示已經逃跑
if(!type){
this.ctx.drawImage(this.boom,this.missile.x-80,this.missile.y-80);//顯示爆炸效果
}
//将飛彈、敵機對象從renderArr中移出
for(var i=0;i<this.renderArr.length;i++){
var item = this.renderArr[i];
if( this.missile==item || this.enemy== item ){
this.renderArr.splice(i,1);
i--;
}
}
//移除目标鎖定對象
var aimWeaponDest = this.aimWeaponDest;
if(aimWeaponDest && aimWeaponDest.length>0){
aimWeaponDest.length=0;
}
this.renderArr2=[];
//移除飛彈
this.missile=null;
//移除敵機
this.enemy=null;
clearInterval(this.timmer);
this.timmer=null;
var msg='目标已摧毀!';
if(type){
msg='目标已逃跑!';
}
//設定延時提示,如果不設定延時,則爆炸效果沒出來就alert了。
setTimeout(function(){
alert(msg);
},200);
}