模拟微信打飞机的demo

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>打飞机</title>

        <style type='css/text'>

                 * {
    margin: 0;
    padding: 0;
}
body {
    overflow-x: hidden;
}
/*加载样式*/
#load {
    /*background: url(../img/loading.gif) no-repeat center center;*/
    
    height: 100%;
    width: 100%;
    position: absolute;
    left: 0;
    top: 0;
}
#load div {
    width: 100px;
    height: 100px;
    border-radius: 50%;
    background: gray;
    color: white;
    line-height: 100px;
    text-align: center;
    font-size: 30px;
    position: absolute;
    top: 0;
    left: 0;
    bottom: 0;
    right: 0;
    margin: auto;
}
#per {
    color: white;
    font-size: 30px;
}
#lt {
    position: absolute;
    left: 0;
    top: 0;
    display: none;
}
#score {
    
}
#game {
    position: absolute;
    left: 0;
    top: 0;
    bottom: 0;
    right: 0;
    margin: auto;
    width: 200px;
    height: 150px;
    border: 1px solid grey;
    background: #ccc;
    display: none;
    text-align: center;
    line-height: 50px;
}
a {
    width: 100px;
    height: 30px;
    font-size: 20px;
    /*border: 2px solid gray;*/
    text-decoration: none;
    color: red;
    display: inline-block;
}





          </style>

    </head>
    <body>
        <!--整体思路
            1.加载样式
            2.背景图移动
            3.玩家飞机  由于玩家只有一个所以可以使用对象的方式去设置,即设置一个对象
            4.敌机  共三种  可以设置为一个类,即设置构造函数,可以使用该构造函数创建三个敌机类
            5.弹夹类型,双弹,清屏弹,激光,也可以是一个类,即设置一个弹夹的构造函数
            6.击中目标,子弹碰到敌机,矩形碰撞
            7.被撞击,敌机撞到玩家飞机,矩形碰撞
            8.计时器,计分器
        -->
        <!--加载样式-->
        <div id="load">
            <div><span id="per">0</span>%</div>
        </div>
        <canvas id="canvas" width="400" height="600"></canvas>
        <!--设置音效-->
        <audio id="gameMusic" src="audio/game_music.mp3" loop="loop" ></audio>
        <audio id="gameOver" src="audio/game_over.mp3"></audio>
        <audio id="bulletMusic" src="audio/bullet.mp3"></audio>
        <audio id="boomMusic1" src="audio/enemy1_down.mp3"></audio>
        <audio id="boomMusic2" src="audio/enemy2_down.mp3"></audio>

        <audio id="boomMusic3" src="audio/enemy3_down.mp3"></audio>

<!--注意音频路径-->

        <div id="lt">
            <span id="score">0</span>分
        </div>
        <div id="game">游戏结束<br />得分:<span id="count"></span><br /><a href="http://127.0.0.1:8020/%E8%AF%BE%E5%A0%82%E4%BB%A3%E7%A0%81/JS/Day26-%E6%89%93%E9%A3%9E%E6%9C%BA%E6%B8%B8%E6%88%8F/game.html">重新开始</a></div>
    </body>

    <script type="text/javascript" charset="utf-8">

         //获取id方法
function getId(id) {
    return document.getElementById(id);
}

//设置img加载
var imgBox = ['img/background.png', 'img/bullet1.png', 'img/bullet2.png', 'img/enemy1.png', 'img/enemy2.png', 'img/enemy3.png', 'img/herofly.png', 'img/prop.png'];
//获取页面当中的dom节点
var canvas = getId("canvas");
var cx = canvas.getContext("2d");
//背景音乐
var gameMusic = getId("gameMusic"); //全局音乐
var gameOver = getId("gameOver"); //玩家死亡音乐
var bulletMusic = getId("bulletMusic"); //枪声
var boomMusic1 = getId("boomMusic1"); //小型敌机声音
var boomMusic2 = getId("boomMusic2"); //中型敌机声音
var boomMusic3 = getId("boomMusic3"); //大型敌机声音

//重新设置canvas大小,使其和window窗口一致
canvas.height = window.innerHeight;
canvas.width = window.innerWidth;

//加载图片
var imgLength = imgBox.length;
var count = 0; //声明循环次数
for (var i = 0; i < imgLength; i++) {
    var img = new Image();
    img.src = imgBox[i];
    //加载完毕
    img.onload = function() {
        count++; //每加载一个就添加一次
        //获取百分比
        var per = Math.floor(count / imgLength * 100);
        getId("per").innerHTML = per;
        //判断是否加载90%
        if (per >= 90) {
            //去掉加载中效果
            getId("load").style.display = "none";
            //添加背景音乐,渲染气氛
            gameMusic.play();
        }
    }
}

//加载图片
//背景图片
var bgImg = new Image();
bgImg.src = imgBox[0];
//玩家图片
var hero = new Image();
hero.src = imgBox[6];
//单行子弹图片
var dBullet = new Image();
dBullet.src = imgBox[1];
//两行子弹图片
var dBullet2 = new Image();
dBullet2.src = imgBox[2];
//道具图片
var prop = new Image();
prop.src = imgBox[7];
//敌机图片
var enemy1 = new Image();
enemy1.src = imgBox[3];
var enemy2 = new Image();
enemy2.src = imgBox[4];
var enemy3 = new Image();
enemy3.src = imgBox[5];

//背景图移动
var h = 0;

function moveBg() {
    h++;
    cx.drawImage(bgImg, 0, h, canvas.width, canvas.height);
    cx.drawImage(bgImg, 0, h - canvas.height, canvas.width, canvas.height);

    //判断复位
    if (h >= canvas.height) {
        h = 0;
    }
}
//设置玩家
var Hero = {
    h: 82, //玩家的高
    w: 66, //玩家的宽
    x: (canvas.width - 66) / 2,
    y: canvas.height - 100,
    bx: 0,
    //绘制玩家
    draw: function() {
        cx.drawImage(hero, this.bx, 0, 66, 82, this.x, this.y, 66, 82);
    }
};

//鼠标拖动事件
window.addEventListener("mousemove", function(event) {
    var x = event.clientX - canvas.offsetLeft;
    var y = event.clientY - canvas.offsetTop;
    //把鼠标的位置给玩家
    Hero.x = x - 33;
    Hero.y = y - 35;
    //防止事件冒泡和默认事件
    event.stopPropagation();
    event.preventDefault();
}, false);

//创建子弹类    x值,y值,宽,高,子弹类型,伤害值
function Bullet(x, y, w, h, buts, hurt) {
    this.x = x;
    this.y = y;
    this.w = w;
    this.h = h;
    this.buts = buts;
    this.hurt = hurt;
}
//存放子弹的数组
var bulletBox = [];
//控制子弹时间间隔,为索引值
var bulletNum = 0;
var box = 6;
//子弹移动
Bullet.prototype.move = function() {
    bulletNum++;
    if (bulletNum >= box) {
        //单行子弹移动
        var b = new Bullet(this.x, this.y, this.w, this.h, this.buts, this.hurt);
        //把子弹放进弹夹
        bulletBox.push(b);

        bulletNum = 0;
    }
    //循环绘制数组中子弹
    for (var i = 0; i < bulletBox.length; i++) {
        var bb = bulletBox[i];
        bb.y -= 5;
        //到达顶部删除数组中的数据
        if (bb.y <= -bb.h) {
            bulletBox.splice(i, 1);
        }
        if (bb) {
            //如果该元素没有从数组中删除则绘制子弹
            cx.drawImage(bb.buts, bb.x, bb.y);
            bulletMusic.play(); //给子弹加声音
        }
    }
};
//创建一个道具类    bx代表从道具图中哪个地方获取道具    speed代表下落速度
function Prop(x, y, w, h, bx, speed) {
    this.x = x;
    this.y = y;
    this.w = w;
    this.h = h;
    this.bx = this.w * bx;
    this.speed = speed;
}
//道具下落方法
Prop.prototype.move = function() {
    this.y += this.speed;
    //绘制道具
    cx.drawImage(prop, this.bx, 0, this.w, this.h, this.x, this.y, this.w, this.h);
};
//创建敌机类
function EnemyPlane(x, y, w, h, type, hp, speed, die, score) {
    this.x = x;
    this.y = y;
    this.w = w;
    this.h = h;
    this.type = type; //敌机类型
    this.hp = hp; //剩余血量
    this.speed = speed;
    this.die = die; //死亡动画
    this.score = score; //不同敌机不同分数
    this.bx = 0;
    this.bol = true; //判断是否爆炸
    this.sayDie = false; //告诉程序对象的死亡状态,便于及时清除敌机残害
}
//敌机爆炸   也就是血量为0
EnemyPlane.prototype.boom = function() {
        this.bol = false;
    }
    //敌机下落
EnemyPlane.prototype.move = function() {

    //绘制敌机
    if (this.bol) {
        this.y += this.speed;
    } else { //死亡
        this.die--; //死亡动画执行的关键帧间隔
        this.bx += this.w; //图片移动
        if (this.die <= 0) { //告知死亡
            this.sayDie = true;
        }
    }
    //绘制敌机
    cx.drawImage(this.type, this.bx, 0, this.w, this.h, this.x, this.y, this.w, this.h);
}

//定义初始值

var score = 0; //设置分数

var enemyArr = []; //设置敌机数组
var lifeBol = true; //玩家活着
var da = true; //判断是否是单双子弹,默认为单
var buttled; //声明子弹类型
var fire = 0; //替换飞机喷火
var heronum = 0;
var baoBol = true; //设置整个页面只有一个子弹包裹的布尔值
var bao; //子弹包裹
var timer = 0; //设置双排子弹出现的关键帧

//设置主函数
function main() {
    //清除画布
    cx.clearRect(0, 0, canvas.width, canvas.height);
    //背景图移动
    moveBg();

    Hero.draw(); //绘制玩家
    //添加敌机
    var enemRan = randomNum(1, 5000); //获取添加敌机的概率
    var butRan = randomNum(1, 3000);
    var baoRan = randomNum(1, 3000); //获取添加子弹类型的概率
    //判断敌机出现的位置
    var x1 = randomNum(0, canvas.width - 38); //设置小敌机出现位置的x坐标
    var x2 = randomNum(0, canvas.width - 46); //设置中敌机出现位置的x坐标
    var x3 = randomNum(0, canvas.width - 110); //设置大敌机出现位置的x坐标
    var x4 = randomNum(0, canvas.width - 38); //设置弹夹出现位置的x坐标
    var enemySpeed = randomNum(5, 10); //设置敌机速度

    //创建敌机
    if (enemRan < 200) {

        //创建小敌机
        enemyArr.push(new EnemyPlane(x1, -34, 38, 34, enemy1, 1, 5, 5, 10));
    }
    if (enemRan > 40 && enemRan < 80) {
        //创建中敌机
        enemyArr.push(new EnemyPlane(x2, -64, 46, 64, enemy2, 3, 4, 6, 50));
    }
    if (enemRan > 100 && enemRan < 110) {
        //创建大敌机
        enemyArr.push(new EnemyPlane(x3, -164, 110, 164, enemy3, 7, 2, 10, 100));
    }
    //创建子弹
    var hx = Hero.x;
    var hy = Hero.y;
    if (lifeBol) { //玩家活着
        fire++; //当飞机正常飞行的时候,改变图的位置,显示喷火效果
        if (fire > 1) {
            fire = 0;
        }
        Hero.bx = Hero.w * fire;

        if (da) { //单行子弹
            //创建单行子弹 6*14
            buttled = new Bullet(hx + 30, hy - 14, 6, 14, dBullet, 10);
        } else { //双行子弹
            buttled = new Bullet(hx + 9, hy - 14, 48, 14, dBullet2, 20);
        }
        buttled.move();
    } else { //如果英雄死亡
        //清空子弹数组
        bulletBox.length = 0;
        heronum++;
        if (heronum % 10 == 0) {
            Hero.bx = Math.floor(heronum / 10) * Hero.w;
        }
    }

    //遍历enemyArr数组  添加敌机
    for (var i = 0; i < enemyArr.length; i++) {
        //遍历子弹数组
        for (var j = 0; j < bulletBox.length; j++) {
            if (enemyArr[i].bol) {
                //判断子弹与敌机相撞
                if (crash(enemyArr[i], bulletBox[j])) {
                    //子弹碰到敌机
                    enemyArr[i].hp -= bulletBox[j].hurt;
                    if (enemyArr[i].hp < 0) {
                        enemyArr[i].boom(); //执行爆炸
                    }
                    //根据每个敌机携带的分数,判断敌机类型,获取相应的分数,添加声音
                    if (enemyArr[i].score == 10) {
                        //小型机
                        boomMusic1.play();
                    } else if (enemyArr[i].score == 50) {
                        //中型机
                        boomMusic2.play();
                    } else if (enemyArr[i].score == 100) {
                        //大型机
                        boomMusic3.play();
                    }
                    //添加分数
                    score += enemyArr[i].score;
                    //删除子弹
                    bulletBox.splice(j, 1);
                }
            }
        }
        //检测玩家撞到了飞机
        if (crash(enemyArr[i], Hero) && lifeBol) {
            lifeBol = false; //玩家死亡
            gameOver.play(); //结束音乐响起
            gameMusic.pause(); //背景音乐暂停
            getId("game").style.display = "block";
        }
        //删除没有碰到子弹和飞机的敌机
        if (enemyArr[i].y > canvas.height) {
            enemyArr.splice(i, 1);
        }

        //绘制敌机
        if (enemyArr[i]) {
            enemyArr[i].move();
            //检测敌机动画执行完毕
            if (enemyArr[i].sayDie) {
                enemyArr.splice(i, 1); //删除敌机
            }
        }
        //添加子弹包裹

        //console.log(butRan < 100 , baoBol);
        if (butRan < 100 && baoBol) { //满足概率,并且添加true
            baoBol = false;
            var typeNum = baoRan < 50 ? 0 : 1;
            bao = new Prop(x4, -68, 38, 68, typeNum, 0.5);

        }
        //当baoBol为false的时候
        if (!baoBol && bao) {
            bao.move();
            //当包裹超出canvas范围时消失    可以重新设置包裹
            if (bao && bao.y > canvas.height) {
                baoBol = true;
            }

            //当包裹和玩家碰撞的时候消失
            if (crash(bao, Hero) && lifeBol) {
                baoBol = true;
                if (bao.bx == 0) { //碰到了清屏弹
                    for (var k = 0; k < enemyArr.length; k++) {
                        enemyArr[k].boom(); //每一个都要执行爆炸方法
                        if (enemyArr[k].score == 10) {
                            boomMusic1.play();
                        } else if (enemyArr[k].score == 50) {
                            boomMusic2.play();
                        } else {
                            boomMusic3.play();
                        }
                        //加分
                        if (enemyArr[k].sayDie) {
                            score += enemyArr[k].score;
                            enemyArr.splice(k, 1);
                        }
                    }
                } else if (bao.bx == 38) { //碰到了双弹
                    da = false;
                    timer = 0;
                }
            }

        }

        if (!da) {
            timer++;
            if (timer > 3000) {
                da = true;
                timer = 0;
            }
        }
    }

    //设置分数
    getId("score").innerHTML = score;
    getId("count").innerHTML = score;
    //执行动画
    requestAnimationFrame(main);
}
//页面资源加载完毕后执行
window.onload = function() {
        //执行主函数
        main();
    }
    //随机数
function randomNum(x, y) {
    return Math.floor(Math.random() * (y - x + 1) + x);
}
//碰撞检测  (矩形碰撞检测)
function crash(obj1, obj2) {

    var x1 = obj1.x;
    var y1 = obj1.y;
    var rx1 = obj1.x + obj1.w / 2;
    var ry1 = obj1.y + obj1.h / 2;

    var x2 = obj2.x;
    var y2 = obj2.y;
    var rx2 = obj2.x + obj2.w / 2;
    var ry2 = obj2.y + obj2.h / 2;

    //判断碰撞
    if (Math.abs(rx1 - rx2) <= (obj1.w + obj2.w) / 2 && Math.abs(ry1 - ry2) <= (obj1.h + obj2.h) / 2) {
        return true;
    } else {
        return false;
    }
}

    </script>

</html>

猜你喜欢

转载自blog.csdn.net/W_Clarence/article/details/73973141