二十八、JS飞机大战demo

  • Post author:
  • Post category:其他




一、第一步:创建地图






分析:创建的地图,要制造飞机一直向上飞行的效果,则要背景无缝循环向下轮播,和之前的无缝轮播一直,只是改变的是

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


<this


.


x


+this


.


width





20







&&




user




.


y


>this


.


y







user




.


height


+


20


&&




user




.


y


<this


.


y


+this


.


height





20


)





{








alert


(


“Game over”


);







clearInterval


(




time_creatShouter




);







clearInterval


(




time_ShouterMove




);







clearInterval


(




time_createEnemy




);







clearInterval


(




time_EnemyMove




);









map




.


onmousemove


=null


;







return


;





}








七、完善代码:



<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title>飞机大战pre</title>
    <style>
        *{margin: 0;padding: 0;}
        .map{
            width: 400px;
            height: 630px;
            border: 1px solid black;
            margin: 2px auto;
           /* cursor: none;*/
            position: relative;
            overflow: hidden;
        }
        .bgmap{
            width: 400px;
            height: 630px;
            background: url("./image/12.png")0 0 no-repeat;
            background-size: 100%;
            position: absolute;
        }
    </style>
</head>
<body>
<div class="map">
    <div class="bgmap"></div>
    <div class="bgmap"></div>
</div>
<script>
    /*创建地图 地图移动*/
    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);
    })();



    /*创建子弹 封装子弹类*/ /*创建用户飞机 封装用户类*/
    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";
        }
    }
    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后继续创建子弹形成连续发射效果
        };
        //构造子弹打到敌机移除二者的方法
        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);
                }
            }
        }
    }

    /*创建敌机 封装敌机类*/
    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";

            //在敌机下落过程中判断是否与飞机相撞 相撞游戏结束
            if(user.x>this.x-user.width+20&&user.x<this.x+this.width-20
             &&user.y>this.y-user.height+20&&user.y<this.y+this.height-20)
            {
                alert("Game over");
                clearInterval(time_creatShouter);
                clearInterval(time_ShouterMove);
                clearInterval(time_createEnemy);
                clearInterval(time_EnemyMove);
                map.οnmοusemοve=null;
                return;
            }
        }
    }

    //定义定时器变量
    var time_creatShouter;
    var time_ShouterMove;
    var time_createEnemy;
    var time_EnemyMove;
    //定义存储子弹的数组  存储敌机的数组
    var shout=[];
    var em_array=[];
    window.οnlοad=function(){
        //实例化用户飞机 调用创建方法
        user=new User();
        user.createUser();
        //实例化子弹 调用创建方法
        time_creatShouter=setInterval(function(){
            shouter=new Shouter();
            shouter.creatShouter(user);
            shout.push(shouter);
        },200);
        //调用子弹移动方法
        time_ShouterMove=setInterval(function(){
            if(shout.length>0){
                for(var i=0;i<shout.length;i++){
                    shout[i].ShouterMove(i,shout);
                    if(em_array.length>0){ //当存在敌机时 被击中会移除
                        if(shout[i]==undefined)return;//处理当飞机飞到顶端的bug
                        shout[i].ShouterEnemy(em_array,i,shout);
                    }
                }
            }
        },5);
        //实例化敌机 调用创建方法
        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)
        //创建地图鼠标移动事件
        map.οnmοusemοve=function(e){
            //鼠标位置-偏移量-用户飞机宽/高
            var x= e.pageX-this.offsetLeft-user.width/2;
            var y= e.pageY-this.offsetTop-user.height/2;
            user.UserMove(x,y);
        }
    }
</script>
</body>
</html>



版权声明:本文为weixin_40976555原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。