二十八、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值,但由于是在第一颗子弹以及减小一次的情况下,才在第一颗子弹的原位置上创建了第二颗子弹,所有第二颗会跟随第一颗子弹的位置移动,依次类推,就形成了不间断的子弹链;

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


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<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>

  • 4
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值