JavaScript(十九)飞机大战demo

用JS实现飞机大战小游戏,效果图如下:

说明:飞机产生子弹的速度并没有如此之快,为了录制gif图,缩短了时间;

思路分析

整体的思路用的是单例模式,使用的方法有构造函数,面向对象,继承等。

一、创建地图,使用的是图片,封装类的方法

二、创建用户飞机,使用封装类的方法

1.在创建用户飞机之前需要创建一个飞机类,之后创建用户飞机和敌机就可以使用继承

2.飞机用图片表示,故在构造飞机创建方法是需创建dom元素img;

3. 另外需获取设置用户飞机的left,top值,根据鼠标移动事件改变用户飞机的left top值,让其跟随鼠标移动,鼠标移动事件中x,y值的获取与之前图片放大镜中覆盖层的鼠标移动事件一致,都需获取鼠标坐标减去偏移量以及自身宽高的一半,而且还要判断飞机移动的上下左右的临界值

 this.mymove = function (x, y) {
            if (this._plane) {
                //计算坐标问题
                this.left = x - this.map.offsetLeft - 40;
                this.top = y - this.map.offsetTop - 40;
                this.x = this.left <= 0 ? 0 : this.left >= 320 ? 320 : this.left;
                this.y = this.top <= -10 ? -10 : this.top >= 540 ? 540 : this.top;
                this._plane.style.left = this.x + "px";
                this._plane.style.top = this.y + "px";
            }
        }

4.最后需要将地图挂载在飞机上。

5.注意:鼠标移动事件是创建给跟随对象的上一元素的,即这里创建给地图,给地图添加监听鼠标事件。

Map._map.addEventListener("mousemove", function () {
            if (Map.mousemove) {
                //鼠标移动的时候控制飞机的移动
                var x = event.pageX || event.clientX;
                var y = event.pageY || event.clientY;
                myPlane.mymove(x, y);
            }
        })

三、创建用户飞机的子弹

1.创建子弹的类,由于子弹都是一组属性相同的数据,所以将子弹实例化对象存储在数组对象中,每创建一颗子弹就追加在数组中

2.子弹同样用一个png图片表示,其创建方法与用户飞机的创建方法一致,只是需要注意的是子弹首发应该显示在飞机中间的上方.(子弹坐标 x=飞机left+飞机自身的一半-子弹自身一半,  y=飞机top-飞机自身的一半)

img.style.left = (parseInt(x) +40-15) + "px";   //x,y 传入参数的值,即是飞机的left值和top值
img.style.top = (parseInt(y) - 10) + "px";

3.创建子弹移动的方法,子弹移动只需要循环改变top值,使子弹的top值不停减小,在子弹飞出地图后,需将子弹移除,在移除子弹时,不仅需移除创建方法中的子弹,还需移除其实例化对象;利用存储实例化子弹数组的截取方法实现(splice方法)

4.在创建子弹和移动子弹都需要控制速度;

5.由于子弹是动态变化时创建的,所以使用定时器调用子弹类

window.requestAnimate = (function () {
    return window.requestAnimationFrame ||
        window.webkitRequestAnimationFrame ||
        window.mozRequestAnimationFrame ||
        function (callback) {
            window.setTimeout(callback, 5000);
        }
})();


(function animaloop() {
    stop = requestAnimate(animaloop);
    //造子弹的方法
    myPlane.showBullet.createBullet(myPlane.x, myPlane.y);
    //子弹移动
    myPlane.showBullet.bulletmove();
})();

6.实例化子弹对象,并将子弹挂载在飞机上,成为飞机的一个属性

 Bullet=new bullet();
 myplane.prototype.showBullet = Bullet;

 四、创建敌机

1.敌机也是一组属性类似的数据,故定义数组来存储;

2.同样需要创建敌机类,并继承飞机类,敌机用图片表示,本案例随机创建10种敌机,大小也随机产生

3.构造敌机的下落方法与子弹原理一致,即改变每个敌机的top属性值

4.子弹击打敌机,需要将敌机挂载到子弹上,判断子弹的left和top值是否在敌机的范围内,若在敌机移除,子弹移除。

 if ( left>= eleft && left <= eleft + ewidth && top <= etop + eheight - 20) {
          //left--子弹   eleft--敌机                        
         this.enemyArray[index].remove();
         this.enemyArray.splice(index, 1);
         this._bullet[i][k].remove();
         this._bullet[i].splice(k, 1);
}

5.当敌机飞出地图,需移除创建方法的敌机还有其实例化对象,同样用实例化存储敌机的数组截取的方法实现;

6.在创建敌机和移动敌机也需要控制速度;

五、游戏结束

设置用户飞机的血量,在敌机未被子弹击中而移除时,血量逐渐减少,直到血量<=0,游戏结束并清除所有定时器;

全部代码

TML+CSS

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
    <style>
        *{
            margin: 0;
            padding: 0;
        }
        .map{
            width: 400px;
            height: 600px;
            margin: 0 auto;
            position: relative;
            border: 1px solid silver;
            background-size: 400px 600px;
            background-repeat: no-repeat;
            cursor: none;

        }
        .my{
            position: absolute;
            width: 80px;
            height: 80px;
        }
        .bullet{
            position: absolute;
            width: 30px;
            height: 30px;
        }
        .enemy{
            position: absolute;
            z-index: 5;
        }
        .score{
            position: absolute;
            top:5px;
            left: 0;
            width: 400px;
            text-align: center;
            color: white;
            font-size: 25px;
            font-family: cursive;
        }
        .blod{
            position: absolute;
            right: -10px;
            bottom: 0;
            border: 1px solid white;
            box-sizing: border-box;
            width: 10px;
            height: 600px;
            background-color: #00df00;
        }
        .sb{
            position: absolute;
            right: 0px;
            bottom: 0;
            width: 8px;
            background-color: red;
            transition: all 0.5s linear;
        }
    </style>
</head>
<body>
<script src="js/index.js"></script>
</body>
</html>

JavaScript

/**
 * Created by Administrator on 2019/2/16.
 */
//创建变量,接收对象
var Map;
var myPlane; //我的飞机
var Enemy;  //敌机
var Bullet; //子弹

var game = (function () {
    //创建地图
    function map() {
        this._map = null;
        this.bgimage = "url(./img/background_1.gif)";
        this.score = 0;
        this.span = null;
        this.blod = 600;
        this.blodele = null;
        this.mousemove = true;
        this.createMap = function () {
            if (this._map == null) {
                this._map = document.createElement("div");
                this._map.className = "map";
                this._map.style.backgroundImage = this.bgimage;
            }
        };
        this.createSpan = function () {
            this.span = document.createElement("span");
            this.span.innerHTML = "Score:" + this.score;
            this.span.className = "score";
            this._map.appendChild(this.span);
        };
        this.createMyBlod = function () {
            this.blodele = document.createElement("div");
            this.blodele.className = "blod";
            var s = document.createElement("div");
            s.className = "sb";
            s.style.height = this.blod + "px";
            this.blodele.appendChild(s);
            this._map.appendChild(this.blodele);
        }
    }

    //创建飞机类
    function plane(img, c, l, t) {   //使用多继承
        this.bgimage = img;
        this.classname = c;
        this.left = l;
        this.top = t;
    }


    //创建我的飞机
    function myplane(img, c, l, t) {
        this._plane = null;
        plane.apply(this, [img, c, l, t]);  //构造继承
        this.x = null;
        this.y = null;
        this.createPlane = function () {
            if (this._plane == null) {
                this._plane = document.createElement("img");
                this._plane.className = this.classname;
                this._plane.src = this.bgimage;
            }
            this._plane.style.left = this.left + "px";
            this._plane.style.top = this.top + "px";
            this.x = this.left;
            this.y = this.top;
            this.map.appendChild(this._plane);
        };
        this.mymove = function (x, y) {
            //计算坐标问题
            if (this._plane) {
                this.left = x - this.map.offsetLeft - 40;
                this.top = y - this.map.offsetTop - 40;
                this.x = this.left <= 0 ? 0 : this.left >= 320 ? 320 : this.left;
                this.y = this.top <= -10 ? -10 : this.top >= 540 ? 540 : this.top;
                this._plane.style.left = this.x + "px";
                this._plane.style.top = this.y + "px";
            }
        }
    }

    //创建敌机
    function enemy() {
        plane.apply(this);
        this.bgimage = ["ep_1.png", "ep_2.png", "ep_3.png", "ep_4.png", "ep_5.png", "ep_6.png", "ep_7.png", "ep_8.png", "ep_9.png", "ep_10.png"];
        this.width = null;
        this.random = 0;
        this.enemyArray = [];
        this.enemyHz = 40;
        this.speed = 5;
        this.enemymoveHz = 2;
        this.createEnemy = function () {
            this.enemyHz--;
            if (this.enemyHz < 0) {
                this.enemyHz = 40;
                //随机产生飞机
                this.random = Math.floor(Math.random() * this.bgimage.length);
                var enemy = document.createElement("img");
                enemy.src = "img/" + this.bgimage [this.random];
                enemy.className = "enemy";
                //setAttribute() 方法创建或改变某个新属性。 添加的属性名,属性值
                enemy.setAttribute("data-blod", Math.random() * 4 + 2);  //敌机的血量,打几次消失
                enemy.setAttribute("data-score", Math.random() * 200 + 100);  //不同的敌机消失加不同的分数
                this.width = (Math.random() * 30 + 70);
                enemy.style.width = this.width + "px";
                enemy.style.height = this.width + "px";
                enemy.style.top = 0 + "px";
                this.left = ( Math.random() * 400);
                enemy.style.left = (this.left - this.width < 0 ? 0 : this.left - this.width) + "px";
                this.enemyArray.push(enemy);
                this.map._map.appendChild(enemy);

            }
        };
        this.enemymove = function () {
            this.enemymoveHz--;
            if (this.enemymoveHz < 0) {
                this.enemymoveHz = 2;
                for (var i = 0; i < this.enemyArray.length; i++) {
                    var top = parseInt(this.enemyArray[i].style.top);
                    top += this.speed;
                    this.enemyArray[i].style.top = top + "px";
                    if (top > 600- (parseInt(this.enemyArray[i].style.width)) ) {
                        this.enemyArray[i].remove();
                        this.enemyArray.splice(i, 1);
                        this.map.blod -= 100;
                        this.map.blodele.children[0].style.height = this.map.blod + "px";
                        if (this.map.blod <= 0) {
                            window.cancelAnimationFrame(stop);  //画面停止
                            this.map.mousemove = false;
                        }
                    }
                }
            }


        }
    }

    //创建子弹
    function bullet() {
        this._bullet = [];
        this.num = 1;
        this.width = null;
        this.className = "bullet";
        this.src = "img/myb_1.png";
        this.createbulletHz = 8;
        this.bulletmoveHz = 1;
        this.speed = 4;
        this.createBullet = function (x, y) {
            this.createbulletHz--;
            if (this.createbulletHz <= 0) {
                this.createbulletHz = 8;
                var but = [];
                for (var i = 0; i < this.num; i++) {
                    var img = document.createElement("img");
                    img.className = this.className;
                    img.src = this.src;
                    if (this.num == 1) {
                        img.style.left = (parseInt(x) + 26) + "px";
                        img.style.top = (parseInt(y) - 10) + "px";
                    }
                    if (this.num == 2) {
                        img.style.left = (parseInt(x) + 4 + (i * 45)) + "px";
                        img.style.top = (parseInt(y) - 10) + "px";
                    }
                    if (this.num == 3) {
                        img.style.left = (parseInt(x) + 4 + (i * 22)) + "px";
                        img.style.top = (parseInt(y) - 10) + "px";
                    }
                    img.style.width = this.width + "px";
                    this.map._map.appendChild(img);
                    but.push(img);
                }
                this._bullet.push(but);
            }


        };
        this.bulletmove = function () {
            this.bulletmoveHz--;
            if (this.bulletmoveHz <= 0) {
                this.bulletmoveHz = 1;
                for (var i = 0; i < this._bullet.length; i++) {
                    for (var k = 0; k < this._bullet[i].length; k++) {

                        if(this._bullet[i][k]){
                            var top = parseInt(this._bullet[i][k].style.top);
                            top -= this.speed;
                            this._bullet[i][k].style.top = top + "px";
                            if (top <= 0) {
                                if (this.num == 1) {
                                    this._bullet[i][k].remove();
                                    this._bullet.splice(i, 1);
                                }
                                else if (this.num == 2) {
                                    this._bullet[i][k].remove();
                                    this._bullet[i].splice(k, 1);
                                }
                                else {
                                    this._bullet[i][k].remove();
                                    this._bullet[i].splice(k, 1);
                                }
                            }
                        }
                    }

                }

                //子弹在移动的过程当中  寻找敌机
                for (var i = 0; i < this._bullet.length; i++) {
                    for (var k = 0; k < this._bullet[i].length; k++) {
                        if (this._bullet[i][k]) {
                            var left = parseInt(this._bullet[i][k].style.left);
                            var top = parseInt(this._bullet[i][k].style.top);
                            var width = parseInt(this._bullet[i][k].style.width);
                            for (var index in this.enemyArray) {
                                //敌机的左上 宽高
                                var eleft = parseInt(this.enemyArray[index].style.left);
                                var etop = parseInt(this.enemyArray[index].style.top);
                                var ewidth = parseInt(this.enemyArray[index].style.width);
                                var eheight = ewidth;

                                //判断是否撞击
                                if (left >= eleft && left <= eleft + ewidth && top <= etop + eheight - 20) {//避免没有碰到就打到飞机
                                    var blod = this.enemyArray[index].getAttribute("data-blod");
                                    blod--;
                                    this.enemyArray[index].setAttribute("data-blod", blod);
                                    if (blod <= 0) {
                                        var score = this.enemyArray[index].getAttribute("data-score");
                                        this.map.score += parseInt(score);
                                        this.map.span.innerHTML = "Score:" + this.map.score;
                                        this.enemyArray[index].remove();
                                        this.enemyArray.splice(index, 1);
                                    }
                                    this._bullet[i][k].remove();
                                    this._bullet[i].splice(k, 1);
                                }
                            }
                        }
                    }

                }
            }

        }


    }


//实例化场景
    function createScene() {
        //实例化地图
        Map = new map();
        Map.createMap();
        Map.createSpan();
        Map.createMyBlod();

        //给地图添加监听事件
        Map._map.addEventListener("mousemove", function () {
            //鼠标移动的时候控制飞机的移动
            var x = event.pageX || event.clientX;
            var y = event.pageY || event.clientY;
            myPlane.mymove(x, y);
        });

        //实例化我的飞机  同时传参
        //挂载飞机到地图上

        //挂载地图到子弹上
        bullet.prototype.map = Map;
        //挂载地图到敌机上
        enemy.prototype.map = Map;

        myplane.prototype.map = Map._map;   //原型链追加
        //实例化子弹并直接挂载到飞机上 成为飞机的一个属性
        Bullet=new bullet();
        myplane.prototype.showBullet =Bullet;


        myPlane = new myplane("img/my_2.png", "my", "160", "500");
        myPlane.createPlane();

        //实例化敌机
        Enemy = new enemy();
        //敌机挂载在子弹上
        bullet.prototype.enemyArray = Enemy.enemyArray;

        return Map._map;
    }

    return {
        getmap: createScene()   //获得该实例的方法
    }
    //单例模式的思路是:一个类能返回一个对象的引用(并且永远是同一个)和一个获得该实例的方法(静态方法,通常使用 getInstance 名称)。
})
();
//添加到页面
document.body.appendChild(game.getmap);
window.requestAnimate = (function () {
    return window.requestAnimationFrame ||
        window.webkitRequestAnimationFrame ||
        window.mozRequestAnimationFrame ||
        function (callback) {
            window.setTimeout(callback, 5000);
        }
})();
(function animaloop() {
    requestAnimate(animaloop);
    //造子弹的方法 反复调用就可出现多个子弹
    myPlane.showBullet.createBullet(myPlane.x, myPlane.y);
    //子弹移动
    myPlane.showBullet.bulletmove();  //竖直向上
    //创建敌机
    Enemy.createEnemy();
    //敌机移动
    Enemy.enemymove();

    if (Map.score < 5000) {
        Bullet.num = 1;
    }
    else if (Map.score < 10000) {
        Bullet.num = 2;
    }
    else {
        Bullet.num = 3;
    }
})();

 

  • 1
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值