飞机大战源码

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title></title>
        <style type="text/css">
            canvas{
                display: block;
                margin: 100px auto;
            }
        </style>
    </head>
    <body>
        <canvas id="canvas" width="480px" height="650px"></canvas>
        <script type="text/javascript">
//          前提
            var canvas = document.getElementById("canvas");
            var context = canvas.getContext("2d");
//          0.游戏初始化

//          0.1 将游戏分为几个阶段
            var START = 0;     //第一个阶段   游戏开始阶段
            var STARTING = 1;  //第二个阶段   游戏运行前的动画阶段
            var RUNNING = 2;   //第三个阶段   游戏运行阶段
            var PAUSE = 3;     //第四个阶段   游戏暂停阶段
            var GAMEOVER = 4;  //第五个阶段   游戏结束阶段
//          0.2 定义自己的状态,跟上面比较,判断游戏处于哪一个阶段
            var state = START;
//          0.3 定义当前画布的宽和高
            var WIDTH = canvas.width;
            var HEIGHT = canvas.height;
//          0.4 定义游戏的得分
            var score = 0;
//          0.5 定义我方飞机的生命值
            var life = 3;

//          1.游戏开始阶段
//          1.1 加载背景图片
//          1.1.1 创建背景图片的对象
            var bg = new Image();
            bg.src = "images/background.png";
//          1.1.2 初始化背景图片的数据
            var BG = {
                imgs : bg,
                width : 480,
                height : 852
            }
//          1.1.3 创建背景图片的  构造器  函数(构造出一个对象)
            function Bg(config){
                this.imgs = config.imgs;
                this.width = config.width;
                this.height = config.height;

                this.x1 = 0;
                this.y1 = 0;
                this.x2 = 0;
                this.y2 = -this.height;
                //定义背景图片绘制的方法
                this.paint = function(){
                    context.drawImage(this.imgs,this.x1,this.y1);
                    context.drawImage(this.imgs,this.x2,this.y2);
                }
                //定义背景图片运动的方法
                this.step = function(){
                    this.y1 ++;
                    this.y2 ++;
//                  判断图片的临界点
                    if(this.y1 == this.height){
                        this.y1 = -this.height;
                    }
                    if(this.y2 == this.height){
                        this.y2 = -this.height;
                    }
                }

            }
//          1.1.4 创建背景图片的对象
            var sky = new Bg(BG)
//          1.2 绘制logo
            var logo = new Image();
            logo.src = "images/start.png"


//          2.游戏运行前动画阶段
//          2.1 加载动画所需要的图片
            var loadings = [];
            loadings[0] = new Image();
            loadings[0].src = "images/game_loading1.png";
            loadings[1] = new Image();
            loadings[1].src = "images/game_loading2.png";
            loadings[2] = new Image();
            loadings[2].src = "images/game_loading3.png";
            loadings[3] = new Image();
            loadings[3].src = "images/game_loading4.png";
//          2.2 初始化图片的数据
            var LOADINGS = {
                imgs : loadings,
                length : loadings.length,
                width : 186,
                height : 38
            }
//          2.3定义开始前动画的构造器
            function Loading(config){
                this.imgs = config.imgs;
                this.length = config.length;
                this.width = config.width;
                this.height = config.height;
//              定义索引,判断显示对应的图片
                this.startIndex = 0;
//              定义绘制方法
                this.paint = function(){
                    context.drawImage(this.imgs[this.startIndex],0,HEIGHT-this.height);
                }
//              定义运动的方法
                this.time = 0;
                this.step = function(){
                    this.time ++;
                    if(this.time % 3 == 0){
                        this.startIndex ++;
                    }
                    if(this.startIndex == this.length){   //如果索引等于长度的时候,就要进入下一个状态
                        state = RUNNING;   //游戏进入第三个阶段
                    }
                }
            }
//          2.4创建游戏运行前动画的对象
            var loading = new Loading(LOADINGS);
//          2.5 第一个阶段的时候,点击画布,切换到第二个阶段
            canvas.onclick = function(){
//              判断,如果为第一阶段的时候点击,才OK
                if(state == START){
                    state = STARTING;
                }
            }

//          3. 游戏运行阶段
//          3.1 绘制我方飞机
//          3.1.1 加载我方飞机所需要用到的图片
            var heros = [];
            heros[0] = new Image();
            heros[0].src = "images/hero1.png";
            heros[1] = new Image();
            heros[1].src = "images/hero2.png";
            heros[2] = new Image();
            heros[2].src = "images/hero_blowup_n1.png";
            heros[3] = new Image();
            heros[3].src = "images/hero_blowup_n2.png";
            heros[4] = new Image();
            heros[4].src = "images/hero_blowup_n3.png";
            heros[5] = new Image();
            heros[5].src = "images/hero_blowup_n4.png";
//          3.1.2 初始化我方飞机的数据
            var HEROS = {
                imgs : heros,
                length : heros.length,
                width : 99,
                height : 124,
                frame : 2      //我方飞机有两种状态,增加标识
            }
//          3.1.3 我方飞机的构造器
            function Hero(config){
                this.imgs = config.imgs;
                this.length = config.length;
                this.width = config.width;
                this.height = config.height;
                this.frame = config.frame;
//              定义索引值
                this.startIndex = 0;
//              定义飞机的位置
                this.x = WIDTH / 2 - this.width / 2;
                this.y = HEIGHT - this.height;
//              定义碰撞属性
                this.down = false;   //false表示没有撞击  
//              定义状态看是否爆破完成
                this.candel = false;

//              定义绘制的方法
                this.paint = function(){
                    context.drawImage(this.imgs[this.startIndex],this.x,this.y);
                }
//              定义运动的方法
                this.step = function(){
//                  两个状态        
//                  1.正常运动状态
//                  2.碰撞以后的状态
                    if(!this.down){    //正常运动的状态
//                      没有撞击的时候,角标在0和1之间进行切换即可
                        if(this.startIndex == 0){
                            this.startIndex = 1;
                        }else{
                            this.startIndex = 0;
                        }
                    }else{     //撞击以后的状态
//                      角标就要不停的增加,模拟出动画
                        this.startIndex ++;
//                      判断是否撞击完成
                        if(this.startIndex == this.length){
                            life --;
                            if(life == 0){
                                state = GAMEOVER;
//                              如果死了,要让动画留到最后一张的爆破图片
                                this.startIndex = this.length - 1;
                            }else{
//                              撞击以后,所有属性全都重置,最简单就是直接new 
                                hero = new Hero(HEROS);
                            }
                        }
                    }
                }
//              飞机的碰撞方法
                this.bang = function(){
                    this.down = true;
                }

//              增加射击的方法
                this.time = 0;
                this.shoot = function(){
                    this.time ++;
                    if(this.time % 3 == 0){
                        bullets.push(new Bullet(BULLET))
                    }
                }

            }

//          3.1.4 创建我方飞机的对象
            var hero = new Hero(HEROS);
//          3.1.5 增加移动事件
            canvas.onmousemove = function(event){
//              console.log(event.offsetX)
                var event = event || window.event;
                if(state == RUNNING){
                    hero.x = event.offsetX - hero.width / 2;
                    hero.y = event.offsetY - hero.height /2;
                }
            }

//          3.2 绘制子弹
//          3.2.1 创建子弹的图片
            var bullet = new Image();
            bullet.src = "images/bullet1.png";
//          3.2.2 初始化子弹的数据
            var BULLET = {
                imgs : bullet,
                width : 9,
                height : 21
            }
//          3.2.3 创建子弹的构造
            function Bullet(config){
                this.imgs = config.imgs;
                this.width = config.width;
                this.height = config.height;
//              定义子弹的坐标
                this.x = hero.x + hero.width / 2 - this.width / 2;
                this.y = hero.y - this.height;
//              绘制方法
                this.paint = function(){
                    context.drawImage(this.imgs,this.x,this.y);
                };
//              运动方法
                this.step = function(){
                    this.y -= 10;
                }
//              增加碰撞属性
                this.candel = false;  //false表示没有碰撞
//              增加碰撞方法
                this.bang = function(){
                    this.candel = true;  
                }
            }
//          3.2.4 所有new 的子弹对象全都放到一个数组中去
            var bullets = [];
//          3.2.5 遍历 - 绘制子弹
            function bulletsPaint(){
                for(var i = 0;i < bullets.length;i++){
                    bullets[i].paint()
                }
            }
//          3.2.6 遍历 - 绘制子弹的运动
            function bulletsStep(){
                for(var i = 0;i < bullets.length;i++){
                    bullets[i].step()
                }
            }
//          3.2.7 子弹的删除
            function bulletsDel(){
//              子弹删除:
//              1.碰撞
//              2.超出画布   y < -子弹的高度 ? 
                for(var i = 0;i < bullets.length;i++){
                    if(bullets[i].candel || bullets[i].y < -bullets[i].height){
                        bullets.splice(i,1);   //第一个参数是选定位置,第二个参数删除几个
                    }
                }
            }

//          3.3 绘制敌方飞机
//          3.3.1 加载敌方飞机的图片
            var enemy1 = [];    //小飞机
            enemy1[0] = new Image();
            enemy1[0].src = "images/enemy1.png"
            enemy1[1] = new Image();
            enemy1[1].src = "images/enemy1_down1.png"
            enemy1[2] = new Image();
            enemy1[2].src = "images/enemy1_down2.png"
            enemy1[3] = new Image();
            enemy1[3].src = "images/enemy1_down3.png"
            enemy1[4] = new Image();
            enemy1[4].src = "images/enemy1_down4.png"
            var enemy2 = [];   //中飞机
            enemy2[0] = new Image();
            enemy2[0].src = "images/enemy2.png"
            enemy2[1] = new Image();
            enemy2[1].src = "images/enemy2_down1.png"
            enemy2[2] = new Image();
            enemy2[2].src = "images/enemy2_down2.png"
            enemy2[3] = new Image();
            enemy2[3].src = "images/enemy2_down3.png"
            enemy2[4] = new Image();
            enemy2[4].src = "images/enemy2_down4.png"
            var enemy3 = [];    //大飞机
            enemy3[0] = new Image();
            enemy3[0].src = "images/enemy3_n1.png"
            enemy3[1] = new Image();
            enemy3[1].src = "images/enemy3_n2.png"
            enemy3[2] = new Image();
            enemy3[2].src = "images/enemy3_down1.png"
            enemy3[3] = new Image();
            enemy3[3].src = "images/enemy3_down2.png"
            enemy3[4] = new Image();
            enemy3[4].src = "images/enemy3_down3.png"
            enemy3[5] = new Image();
            enemy3[5].src = "images/enemy3_down4.png"
            enemy3[6] = new Image();
            enemy3[6].src = "images/enemy3_down5.png"
            enemy3[7] = new Image();
            enemy3[7].src = "images/enemy3_down6.png"
//          3.3.2 初始化敌方飞机的数据
            var ENEMY1 = {
                imgs : enemy1,
                length : enemy1.length,
                width: 57,
                height : 51,
                type : 1,
                frame : 1,
                life : 2,
                score : 2
            }
            var ENEMY2 = {
                imgs : enemy2,
                length : enemy2.length,
                width: 69,
                height : 95,
                type : 2,
                frame : 1,
                life : 4,
                score : 8
            }
            var ENEMY3 = {
                imgs : enemy3,
                length : enemy3.length,
                width: 165,
                height : 261,
                type : 3,
                frame : 2,
                life : 14,
                score : 20
            }
//          3.3.3 敌方飞机的构造
            function Enemy(config){
                this.imgs = config.imgs;
                this.length = config.length;
                this.width = config.width;
                this.height = config.height;
                this.type = config.type;
                this.frame = config.frame;
                this.life = config.life;
                this.score = config.score;
//              定义坐标
                this.x = Math.random() * (WIDTH - this.width);
                this.y = -this.height;
//              定义下标
                this.startIndex = 0;
//              碰撞属性
                this.down = false;
//              动画是否执行完成的属性
                this.candel = false;
//              绘制方法
                this.paint = function(){
                    context.drawImage(this.imgs[this.startIndex],this.x,this.y);
                }
//              运动方法
                this.step = function(){
                    if(!this.down){    //飞机处于正常状态
//                      小飞机,中飞机的下标始终都是0
//                      大飞机的下标是在0和1之间进行切换

                        this.startIndex ++;
                        this.startIndex = this.startIndex % this.frame;

//                      飞机向下的动画
                        this.y += 2
                    }else{          //飞机发生碰撞以后
                        this.startIndex ++;
                        if(this.startIndex == this.length){
                            this.candel = true;
                            this.startIndex = this.length - 1
                        }
                    }
                }
//              是否被撞击的方法
                this.checkHit = function(wo){   //碰撞的时候,可能为我方飞机,可能子弹
                    return wo.y + wo.height > this.y 
                           && wo.x + wo.width > this.x
                           && wo.y < this.y + this.height
                           && wo.x < this.x + this.width;
                }
//              敌方飞机碰撞以后的方法
                this.bang = function(){
                    this.life --;
                    if(this.life == 0){
                        this.down = true;
                        score += this.score;
                    }
                }
            }
//          3.3.4 创建数组,用于存放敌方飞机
            var enemies = [];
//          3.3.5 往数组中去添加飞机
            function enterEnemise(){

                var rand = Math.floor(Math.random() * 100);
                if(rand < 10){   //添加小飞机
                    enemies.push(new Enemy(ENEMY1))
                }else if(rand < 55 && rand > 50){
                    enemies.push(new Enemy(ENEMY2))
                }else if(rand == 88){
//                  大飞机有且只能有一个
//                  把大飞机放在数组的第一位            
                    if(enemies[0].type != 3 && enemies.length > 0){
                        enemies.splice(0,0,new Enemy(ENEMY3))
                    }
                }
            }
//          3.3.6 创建函数   绘制敌方飞机
            function paintEnemise(){
                for(var i = 0;i< enemies.length;i++){
                    enemies[i].paint();
                }
            }
//          3.3.7 创建函数 绘制敌方飞机运动
            function stepEnemise(){
                for(var i = 0;i< enemies.length;i++){
                    enemies[i].step();
                }
            }
//          3.3.8 创建函数,用于删除飞机
            function delEnemise(){
                for(var i = 0;i< enemies.length;i++){
                    if(enemies[i].y > HEIGHT || enemies[i].candel){
                        enemies.splice(i,1)
                    }
                }
            }

//          3.4 绘制碰撞以后的函数
            function hitEnemise(){
                for(var i = 0;i< enemies.length;i++){
//                  如果我方飞机撞到了敌方飞机以后
                    if(enemies[i].checkHit(hero)){
//                      处理敌方飞机碰撞以后的逻辑
                        enemies[i].bang();
//                      处理我方飞机碰撞以后的逻辑
                        hero.bang()
                    }

//                  子弹如果碰到敌方飞机以后
                    for(var j = 0;j<bullets.length;j++){
                        if(enemies[i].checkHit(bullets[j])){
                            enemies[i].bang();
//                          子弹的碰撞逻辑
                            bullets[j].bang()
                        }
                    }
                }
            }

//          3.5 绘制得分和我方飞机的生命值
            function paintText(){
                context.font = "bold 30px 微软雅黑"
                context.fillText("SCORE:" + score,10,30);
                context.fillText("LIFE:" + life,380,30 )
            }

//          4.游戏暂停阶段
            canvas.onmouseover = function(){
                if(state == PAUSE){
                    state = RUNNING
                }
            }
            canvas.onmouseout = function(){
                if(state == RUNNING){
                    state = PAUSE
                }
            }
            var pause = new Image();
            pause.src="images/game_pause_nor.png";

//          5.GAMEOVER文本
            function paintOver(){
                context.font = "bold 40px 微软雅黑"
                context.fillText("GAME OVER!!!",100,300)
            }


            setInterval(function(){
//              因为背景图片时刻都在运动
                sky.paint();
                sky.step();
                if(state == START){
                    context.drawImage(logo,30,0)
                }else if(state == STARTING){
                    loading.paint();
                    loading.step();
                }else if(state == RUNNING){
//                  我方飞机的绘制
                    hero.paint();
//                  我方飞机的运动
                    hero.step();
//                  我方飞机的射击方法
                    hero.shoot();
//                  绘制子弹
                    bulletsPaint();
//                  绘制子弹的运动
                    bulletsStep();
//                  删除子弹
                    bulletsDel()

//                  创建敌方飞机
                    enterEnemise()
//                  绘制敌方飞机
                    paintEnemise()
//                  绘制敌方飞机的运动
                    stepEnemise()
//                  敌方飞机的删除
                    delEnemise()
//                  是否撞击
                    hitEnemise()
//                  绘制文字
                    paintText()
                }else if(state == PAUSE){
                    hero.paint();
                    bulletsPaint();
                    paintEnemise()
                    paintText()
                    context.drawImage(pause,200,300)
                }else if(state == GAMEOVER){
                    hero.paint();
                    bulletsPaint();
                    paintEnemise()
                    paintText()
                    paintOver()
                }
            },50)
        </script>
    </body>
</html>

猜你喜欢

转载自blog.csdn.net/weixin_42940821/article/details/82257057