一、第一步:创建地图
分析:创建的地图,要制造飞机一直向上飞行的效果,则要背景无缝循环向下轮播,和之前的无缝轮播一直,只是改变的是top值;
Html代码 :
<div class="map">
<div class="bgmap">div>
<div class="bgmap">div>
div>
封装地图无缝轮播方法:
/*创建地图 地图移动*/
var map=document.getElementsByClassName("map")[0];
(function (){ //(function(){})();即自调用函数function(){}
var bgmap=document.getElementsByClassName("bgmap");
//设置背景图片初始top值
bgmap[0].style.top="-630px";
bgmap[1].style.top="0px";
//封装背景图片由上自下移动事件
function bgmove(){
for(var i=0;i<bgmap.length;i++){
var Top=parseInt(bgmap[i].style.top);
Top++;
if(Top>=630){
Top=-630;
}
bgmap[i].style.top=Top+"px";
}
}
setInterval(bgmove,30);
})();
二、创建用户飞机,使用封装类的方法
分析:1.飞机用图片表示,故在构造飞机创建方法是需创建dom元素img;
2. 另外需获取设置用户的left,top值,根据鼠标移动事件改变用户飞机的left top值,让其跟随鼠标移动,鼠标移动事件中x,y值的获取与之前放大镜中覆盖层的鼠标移动事件一致,都需获取鼠标坐标减去偏移量以及自身宽高的一半
注意:鼠标移动事件是创建给跟随对象的上一元素的,即这里创建给地图;
/*创建用户飞机 封装用户类*/
var user;//实例化的全局变量
function User(){
this.width=60;
this.height=70;
this.position="absolute";
this.userf=null;
this.src="./image/14.gif";
this.x;
this.y;
//构造创建用户飞机的方法
this.createUser=function(){
if(this.userf==null){
this.userf=document.createElement("img");
this.userf.style.width=this.width+"px";
this.userf.style.height=this.height+"px";
this.userf.style.position=this.position;
this.userf.style.zIndex=1;
this.userf.src=this.src;
this.userf.style.left="170px";//400/2-60/2
this.userf.style.top="530px";//630-70-30
map.appendChild(this.userf);
}
};
//构造用户飞机移动方法
this.UserMove=function(x,y){ //传参 利用地图鼠标移动事件获取鼠标坐标控制
this.x=x;
this.y=y;
this.userf.style.left=x+"px";
this.userf.style.top=y+"px";
}
}
鼠标移动事件:
//创建地图鼠标移动事件
map.onmousemove=function(e){
//鼠标位置-偏移量-用户飞机宽/高
var x= e.pageX-this.offsetLeft-user.width/2;
var y= e.pageY-this.offsetTop-user.height/2;
user.UserMove(x,y);
三、用户飞机的子弹
创建子弹的类,由于子弹也是一组属性一致的数据,所以定义数组存储子弹的实例化对象;每创建一颗子弹向数组中追加一颗;
分析:1.创建一个类,并构造子弹的创建方法,子弹同样用一个png图片表示,其创建方法与用户飞机的创建方法一致,只是需要注意的是子弹首发应该显示在飞机中间的上方.(子弹坐标 x=飞机left+飞机自身的一半-子弹自身一半 y=飞机top-飞机自身的一半)
2.创建子弹的移动方法:
子弹移动只需要循环改变top值,使子弹的top值不停减小,但当第一颗子弹移动到下一移位置,在第一颗再次创建一颗子弹, 虽然对这两颗子弹都在不停减小top值,但由于是在第一颗子弹以及减小一次的情况下,才在第一颗子弹的原位置上创建了第二颗子弹,所有第二颗会跟随第一颗子弹的位置移动,依次类推,就形成了不间断的子弹链;
注意:在子弹飞出地图后,需将子弹移除,在移除子弹时,不仅需移除创建方法中的子弹,还需移除其实例化对象;利用存储实例化子弹数组的截取方法实现;
var shouter;
function Shouter(){
this.width=10;
this.height=20;
this.shouterf=null;
this.position="absolute";
this.src="./image/15.png";
this.x;
this.y;
//构造创建子弹的方法
this.creatShouter=function(User){
if(this.shouterf==null){
this.shouterf=document.createElement("img");
this.shouterf.style.width=this.width+"px";
this.shouterf.style.height=this.height+"px";
this.shouterf.style.position=this.position;
this.shouterf.style.zIndex=1;
this.shouterf.src=this.src;
map.appendChild(this.shouterf);
//子弹坐标 x=飞机left+飞机自身的一半-子弹自身一半
//y=飞机top-飞机自身的一半
this.x=parseInt(user.userf.style.left)+user.width/2-this.width/2;
this.y=parseInt(user.userf.style.top)-user.height/2;
}
this.shouterf.style.left=this.x+"px";
this.shouterf.style.top=this.y+"px";
};
//构造子弹移动的方法
this.ShouterMove=function(index,array){
this.y-=2; //子弹的top值
if(this.y<=0){//当子弹飞出屏幕 移除创建的子弹及其实例化对象
this.shouterf.remove();
array.splice(index,1);//移除实例化数组中的子弹 利用数组截取的方法
}
this.creatShouter();//改变top后继续创建子弹形成连续发射效果
};
}
由于子弹是动态变化时创建的,所以使用定时器调用子弹类
//实例化子弹 调用创建方法
time_creatShouter=setInterval(function(){
shouter=new Shouter();
shouter.creatShouter(user);
shout.push(shouter);
},200);
由于是改变每颗子弹自身的top值,所以调用子弹移动方法时需遍历子弹数组,注意先得判断是否有子弹生成
//调用子弹移动方法
time_ShouterMove=setInterval(function(){
if(shout.length>0){
for(var i=0;i<shout.length;i++){
shout[i].ShouterMove(i,shout);
}
},5);
四、敌机的创建及移动
分析:1.敌机也是一组属性类似的数据,故定义数组来存储;
2.同样需要创建敌机类,敌机用图片表示,这里创建2种敌机,大敌机和小敌机;
注意:将小敌机的属性设置为默认值,大敌机属性传参数设置;
3.构造敌机的下落方法与子弹原理一致,即改变每个敌机的top属性值;
注意:当敌机飞出地图,需移除创建创建方法的敌机还有其实例化对象,同样用实例化存储敌机的数组截取的方法实现;
/*创建敌机 封装敌机类*/
var enemy;
function Enemy(width,height,blood,score,s){
//敌机分为2种
this.width=width||40;
this.height=height||30;
this.blood=blood||3;
this.score=score||100;
this.enemyf=null;
this.src=s||"./image/17.png";
this.speed=2;
this.position="absolute";
this.x;//x轴 left
this.y;//y轴 top
//构造创建敌机的方法
this.createEnemy=function(){
if(this.enemyf==null){
this.enemyf=document.createElement("img");
this.enemyf.style.width=this.width+"px";
this.enemyf.style.height=this.height+"px";
this.enemyf.style.position=this.position;
this.enemyf.style.zIndex=2;
this.enemyf.src=this.src;
map.appendChild(this.enemyf);
//随机产生起始线不同位置的敌机
this.x=Math.random()*(400-this.width);
this.y=-this.height;
}
this.enemyf.style.left=this.x+"px";
this.enemyf.style.top=this.y+"px";
}
//构造敌机下落的方法
this.EnemyMove=function(index,array){
//改变敌机的top值 赋回去
this.y+=this.speed;
if(this.y>630){//敌机飞出界面 移除创建的敌机及实例化对象
this.enemyf.remove();
array.splice(index,1);//移除实例化数组中的敌机 利用数组截取的方法
count++;
}
this.enemyf.style.top=this.y+"px";
}
实例化敌机类,并调用飞机的创建方法,使用Math方法中的随机数方法控制大小敌机创建的比例;
//实例化敌机 调用创建方法
time_createEnemy=setInterval(function(){
//利用随机数控制大小敌机创建比例
if(Math.random()<0.7){
enemy=new Enemy();
enemy.createEnemy();
em_array.push(enemy);
}
else{
enemy=new Enemy(50,65,5,300,"./image/18.png");
enemy.createEnemy();
em_array.push(enemy);
}
},1000);
敌机的下落方法的调用,与子弹移动方法调用一致,都需循环调用对每个敌机调用该下落方法;
//调用敌机移动方法
time_EnemyMove=setInterval(function(){
if(em_array.length>0){
for(var key in em_array){
em_array[key].EnemyMove(key,em_array);
}
}
},15)
五、实现击打敌机效果
分析:是否打中敌机,其判断方法和贪吃蛇吃豆豆方法类似,即对比left,top值,只是这里子弹击中范围需控制在敌机大小区域内,并且在击中敌机后这可子弹将被移除,在被子弹击中几次之后,敌机也将被移除。(几次将由敌机属性中的血量控制,每被击中一次血量掉一格,血量小于等于0时将敌机移除)
注意:这里移除也需移除创建对象及其实例化的对象
//构造子弹打到敌机移除二者的方法
this.ShouterEnemy=function(enemyarr,index,shoutarr){ //传参 子弹数组 敌机数组 移除所用缩引
for(var key in enemyarr){ //遍历敌机数组
//判断 子弹x y 值范围在敌机区域 移除
if(this.x>enemyarr[key].x-this.width&&this.x<enemyarr[key].x+enemyarr[key].width
&&this.y>enemyarr[key].y-this.height&&this.y<enemyarr[key].y+enemyarr[key].height){
//大小敌机血量不同 当血量为0时 移除被击打的敌机及其实例化对象
enemyarr[key].blood-=1;
if(enemyarr[key].blood<=0){
enemyarr[key].enemyf.remove();
enemyarr.splice(key,1);
}
//同时移除击打中敌机的子弹及实例化对象
this.shouterf.remove();
shoutarr.splice(index,1);
}
}
六、飞机敌机相撞 游戏结束
分析:在敌机的下落方法中判断用户飞机是否进入了敌机大小区域,进入即视为相撞,游戏结束并清除所有定时器;
注意:alter()优于其他代码,故当点击确定后还会执行一次定时器;
//在敌机下落过程中判断是否与飞机相撞 相撞游戏结束
if(user.x>this.x-user.width+20&&user.x
&&user.y>this.y-user.height+20&&user.y
{
alert("Game over");
clearInterval(time_creatShouter);
clearInterval(time_ShouterMove);
clearInterval(time_createEnemy);
clearInterval(time_EnemyMove);
map.onmousemove=null;
return;
}
七、完善代码:
飞机大战pre