二十八、JS飞机大战demo

一、第一步:创建地图

分析:创建的地图,要制造飞机一直向上飞行的效果,则要背景无缝循环向下轮播,和之前的无缝轮播一直,只是改变的是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. 另外需获取设置用户的lefttop值,根据鼠标移动事件改变用户飞机的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值,但由于是在第一颗子弹以及减小一次的情况下,才在第一颗子弹的原位置上创建了第二颗子弹,所有第二颗会跟随第一颗子弹的位置移动,依次类推,就形成了不间断的子弹链;

注意:在子弹飞出地图后,需将子弹移除,在移除子弹时,不仅需移除创建方法中的子弹,还需移除其实例化对象;利用存储实例化子弹数组的截取方法实现;

二十八、JS飞机大战demo_第1张图片

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)

 

五、实现击打敌机效果

分析:是否打中敌机,其判断方法和贪吃蛇吃豆豆方法类似,即对比lefttop值,只是这里子弹击中范围需控制在敌机大小区域内,并且在击中敌机后这可子弹将被移除,在被子弹击中几次之后,敌机也将被移除。(几次将由敌机属性中的血量控制,每被击中一次血量掉一格,血量小于等于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.x+this.width-20
 &&user.y>this.y-user.height+20&&user.y.y+this.height-20)
{
    alert("Game over");
    clearInterval(time_creatShouter);
    clearInterval(time_ShouterMove);
    clearInterval(time_createEnemy);
    clearInterval(time_EnemyMove);
    map.onmousemove=null;
    return;
}


七、完善代码:




    
    飞机大战pre
    



你可能感兴趣的:(前端)