1. 程式人生 > >模擬微信打飛機的demo

模擬微信打飛機的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>