canvas实习飞机大战小游戏

canvas实习飞机大战小游戏
在这里插入图片描述
在这里插入图片描述
具体实现代码如下:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>飞机大战</title>
    <style>
        canvas {
    
    
            border: 1px solid;
            display: block;
            margin: 0 auto;
        }
    </style>
</head>

<body>
    <canvas width="500px" height="800px"></canvas>

    <script>
        var canvas = document.getElementsByTagName("canvas")[0];
        var ctx = canvas.getContext("2d");

        // 初始化数据
        var START = 0;
        var STARTING = 1;
        var RUNNING = 2;
        var PAUSE = 3;
        var GAMEOVER = 4;

        // 记录游戏的状态变化
        var state = START;
        // 获取画布的宽和高
        var HEIGHT = canvas.height;
        var WIDTH = canvas.width;
        // 游戏的分数
        var score = 0;
        // 我方飞机的生命值
        var life = 3;

        // 将游戏分为几个阶段
        // 1 准备阶段 使用定时器绘制背景图和logo
        // 1.1 运动的背景图片
        // 1.1.1创建图片对象
        var bg = new Image();
        bg.src = "img/background.png"

        // 定义图片信息
        var BG = {
    
    
            width: WIDTH,
            height: HEIGHT,
            img: bg
        }

        // 创建背景图片的构造函数
        function Bg(parmas) {
    
    
            this.width = parmas.width;
            this.height = parmas.height;
            this.img = parmas.img;

            // 绘制图片的坐标
            this.x = 0;
            this.y = 0;
            this.x1 = 0;
            this.y1 = -this.height;
            // 定义绘制图片的方法
            this.paint = function () {
    
    
                ctx.drawImage(this.img, this.x, this.y, this.width, this.height)
                ctx.drawImage(this.img, this.x1, this.y1, this.width, this.height)
            }
            // 图片的运动
            this.step = function () {
    
    
                this.y += 10;
                this.y1 += 10;
                if (this.y1 >= this.height) {
    
    
                    this.y1 = -this.height;
                }
                if (this.y >= this.height) {
    
    
                    this.y = -this.height;
                }
            }
        }
        var sky = new Bg(BG)
        // 1.2 logo
        // 1.2.1创建logo对象
        var logo = new Image();
        logo.src = "img/start.png"

        // 2 游戏加载阶段 点击画布触发开始游戏
        // 2.1点击canvas触发当前状态
        canvas.onclick = function () {
    
    
            if (state == START) {
    
    
                state = STARTING;
            }
        }
        // 2.2 绘制我方飞机
        // 把图片的地址存入数组中
        var imgArr = ["img/game_loading1.png", "img/game_loading2.png", "img/game_loading3.png",
            "img/game_loading4.png"
        ]
        var img = [];
        for (var i = 0; i < imgArr.length; i++) {
    
    
            img[i] = new Image();
            img[i].src = imgArr[i]
        }

        var LOADING = {
    
    
            imgs: img,
            length: img.length,
            width: 186,
            height: 38
        }

        // 创建构造函数
        function Loading(parmas) {
    
    
            this.imgs = parmas.imgs;
            this.length = parmas.length;
            this.width = parmas.width;
            this.height = parmas.height;

            // 记录当前照片索引值
            this.startIndex = 0;
            // 开始绘制
            this.paint = function () {
    
    
                // console.log(loading);
                ctx.drawImage(this.imgs[this.startIndex], 0, HEIGHT - this.height)
                this.startIndex++;
                if (this.startIndex == this.length) {
    
    
                    state = RUNNING;
                }
            }
        }

        var loading = new Loading(LOADING)

        // 3 游戏进行中 游戏加载完成后进入该阶段
        // 3.1 我方飞机跟随鼠标移动包括子弹的发射
        // 3.1.1创建我方飞机
        var heros = ['img/hero1.png', 'img/hero2.png', 'img/hero_blowup_n1.png', 'img/hero_blowup_n2.png',
            'img/hero_blowup_n3.png', 'img/hero_blowup_n4.png'
        ];
        var img = [];
        for (var i = 0; i < heros.length; i++) {
    
    
            img[i] = new Image();
            img[i].src = heros[i];
        }
        // 3.1.2我方飞机详细信息
        var HEROS = {
    
    
            imgs: img,
            length: img.length,
            width: 99,
            height: 124,
            frame: 2 //记录飞行状态

        }
        // 3.1.2我方飞机构造函数
        function Heros(parmas) {
    
    
            this.imgs = parmas.imgs;
            this.length = parmas.length;
            this.width = parmas.width;
            this.height = parmas.height;
            this.frame = parmas.frame;

            // 索引记录当前飞机的下标
            this.startIndex = 0;
            //飞机的坐标
            this.x = WIDTH / 2 - this.width / 2;
            this.y = HEIGHT - this.height - 10;

            this.paint = function () {
    
    
                ctx.drawImage(this.imgs[this.startIndex], this.x, this.y)
            }
            // 记录是否发生了碰撞,false表示没有,true有
            this.down = false;
            // 定义飞机是否爆破完成,表示飞机还没有完全爆炸
            this.candel = false;
            // 我方飞机运动方法
            this.step = function () {
    
    
                if (this.down) {
    
    
                    this.startIndex++;
                    // 在碰撞的动画执行完成后
                    if (this.startIndex == this.length) {
    
    
                        life--;
                        // 检查生命值是否为0
                        if (life == 0) {
    
    
                            state = GAMEOVER;
                            this.startIndex = this.length - 1;
                        } else {
    
    
                            hero = new Heros(HEROS);
                        }
                    }
                } else {
    
    
                    //正常状态,没有发生碰撞
                    //切换索引0/1
                    if (this.startIndex == 0) {
    
    
                        this.startIndex = 1;
                    } else {
    
    
                        this.startIndex = 0;
                    }
                }
            }
            // 碰撞方法
            this.bang = function () {
    
    
                this.down = true;
            }
            this.time = 0
            //射击方法
            this.shoot = function () {
    
    
                this.time++;
                if (this.time % 3 == 0) {
    
    
                    // 子弹的数组里面添加子弹对象
                    bullets.push(new Bullet(BULLET));
                }
            }
        }
        var hero = new Heros(HEROS);
        //3.1.4飞机跟鼠标移动
        canvas.addEventListener("mousemove", function (e) {
    
    
            // 获取鼠标的触发事件的当前位置
            var x = e.offsetX;
            var y = e.offsetY;

            // 将值赋值给飞机的x,y坐标
            if (state == RUNNING) {
    
    
                hero.x = x - hero.width / 2;
                hero.y = y - hero.height / 2;
            }
        })

        // 3.1.5 绘制子弹
        var bullet = new Image();
        bullet.src = 'img/bullet1.png';
        var BULLET = {
    
    
            img: bullet,
            width: 9,
            height: 21
        }
        //子弹构造
        function Bullet(parmas) {
    
    
            this.img = parmas.img;
            this.width = parmas.width;
            this.height = parmas.height;

            // 坐标
            this.x = hero.x + hero.width / 2 - this.width / 2;
            this.y = hero.y - this.height;

            //绘制方法
            this.paint = function () {
    
    
                ctx.drawImage(this.img, this.x, this.y)
            }
            //子弹移动
            this.step = function () {
    
    
                this.y -= 10;
            }
            // 判断子弹是否碰撞
            this.candel = false;
            // 子弹碰撞方法
            this.bang = function () {
    
    
                this.candel = true;
            }


        }
        // 创建子弹数组
        var bullets = [];
        // 遍历绘制子弹
        function bulletdPaint() {
    
    
            for (var i = 0; i < bullets.length; i++) {
    
    
                bullets[i].paint();
            }
        };
        // 遍历调用子弹的运动;
        function bulletdStep() {
    
    
            for (var i = 0; i < bullets.length; i++) {
    
    
                bullets[i].step();
            }
        };
        // 子弹的删除函数
        function bulletDel() {
    
    
            // 碰撞的时候删除子弹
            // 超出画布的高度,即负的子弹的高度
            for (var i = 0; i < bullets.length; i++) {
    
    
                if (bullets[i].candel || bullets[i].y < -bullets[i].height) {
    
    
                    bullets.splice(i, 1)
                }
            }
        };
        // 3.2 随机绘制敌机
        // 绘制小飞机
        var enemy1Arr = ["img/enemy1.png", "img/enemy1_down1.png", "img/enemy1_down2.png", "img/enemy1_down3.png",
            "img/enemy1_down4.png"
        ]
        var enemy1 = [];
        for (var i = 0; i < enemy1Arr.length; i++) {
    
    
            enemy1[i] = new Image();
            enemy1[i].src = enemy1Arr[i];
        }
        var ENEMY1 = {
    
    
            imgs: enemy1,
            length: enemy1.length,
            width: 57,
            height: 51,
            type: 1,
            frame: 1,
            life: 1,
            score: 1,
        };
        //绘制中飞机
        var enemy2Arr = ["img/enemy2.png", "img/enemy2_down1.png", "img/enemy2_down2.png", "img/enemy2_down3.png",
            "img/enemy2_down4.png"
        ]
        var enemy2 = [];
        for (var i = 0; i < enemy2Arr.length; i++) {
    
    
            enemy2[i] = new Image();
            enemy2[i].src = enemy2Arr[i];
        }
        var ENEMY2 = {
    
    
            imgs: enemy2,
            length: enemy2.length,
            width: 69,
            height: 95,
            type: 2,
            frame: 1,
            life: 5,
            score: 5,
        };
        // 绘制大飞机
        var enemy3Arr = ["img/enemy3_n1.png", "img/enemy3_n2.png", "img/enemy3_down1.png", "img/enemy3_down2.png",
            "img/enemy3_down3.png",
            "img/enemy3_down4.png", "img/enemy3_down5.png", "img/enemy3_down6.png"
        ]
        var enemy3 = [];
        for (var i = 0; i < enemy3Arr.length; i++) {
    
    
            enemy3[i] = new Image();
            enemy3[i].src = enemy3Arr[i];
        }
        var ENEMY3 = {
    
    
            imgs: enemy3,
            length: enemy3.length,
            width: 165,
            height: 261,
            type: 3,
            frame: 2,
            life: 15,
            score: 20,
        };
        //敌方飞机的构造函数
        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 () {
    
    
                ctx.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;
                }
            }
        };
        // 数组存放敌方飞机
        var enemise = [];
        // 往敌方飞机数组中添加数据
        function enterEnemise() {
    
    
            var rand = Math.floor(Math.random() * 100)
            if (rand < 10) {
    
    
                // 添加小飞机
                enemise.push(new Enemy(ENEMY1));
            } else if (rand < 55 && rand > 50) {
    
    
                // 添加中飞机
                enemise.push(new Enemy(ENEMY2));
            } else if (rand === 88) {
    
    
                // 添加大飞机
                if (enemise[0].type !== 3 && enemise.length > 0) {
    
    
                    enemise.splice(0, 0, new Enemy(ENEMY3));
                }
            }
        };
        // 绘制敌方飞机函数
        function enemyPaint() {
    
    
            for (var i = 0; i < enemise.length; i++) {
    
    
                enemise[i].paint();
            }
        };
        // 敌方飞机的运动函数
        function enemyStep() {
    
    
            for (var i = 0; i < enemise.length; i++) {
    
    
                enemise[i].step();
            }
        };
        // 删除敌方飞机函数
        function delenemy() {
    
    
            for (var i = 0; i < enemise.length; i++) {
    
    
                // console.log(enemise[i].candel)
                if (enemise[i].y > HEIGHT || enemise[i].candel) {
    
    
                    enemise.splice(i, 1)
                }
            }
        };
        // 碰撞以后的函数
        function hitEnemise() {
    
    
            for (var i = 0; i < enemise.length; i++) {
    
    
                // 如果我放飞机撞到了敌方飞机以后
                if (enemise[i].checkHit(hero)) {
    
    
                    // 敌方飞机碰撞后,碰撞状态改变
                    enemise[i].bang();
                    // 我方飞机碰撞后,碰撞状态改变
                    hero.bang();
                };
                // 子弹碰到敌方飞机
                for (var j = 0; j < bullets.length; j++) {
    
    
                    if (enemise[i].checkHit(bullets[j])) {
    
    
                        enemise[i].bang();
                        // 子弹的碰撞后,碰撞状态改变
                        bullets[j].bang();
                    }
                }
            }
        };
        // 绘制分数和生命值
        function scoreText() {
    
    
            ctx.font = "30px bold"
            ctx.fillText("分数:" + score, 10, 30);
            ctx.fillText("生命:" + life, 300, 30);
        };
        // 游戏结束
        function gameoverfn() {
    
    
            ctx.font = "50px bold"
            ctx.fillText("GAME OVER !!!", 80, 300);
            ctx.fillText("ONCE MORE !!!", 80, 400);
        };

        canvas.addEventListener("click", function (e) {
    
    
            p = getEventPosition(e);
            // 点击画布时,判断游戏是否开始
            if (state === START){
    
    
                state = STARTING;
            }

            // 重新开始游戏有问题???
            if (state === GAMEOVER) {
    
    
                if (p.y >= 350 && p.y < 450) {
    
    
                    history.go(0);
                }
            }
        });

        function getEventPosition(e) {
    
    
                var x, y;
                if (e.layerX || ev.layerX === 0) {
    
    
                    x = e.layerX;
                    y = e.layerY;
                } else if (e.offsetX || ev.offsetX === 0) {
    
    
                    x = e.offsetX;
                    y = e.offsetY;
                }
                return {
    
    
                    x: x,
                    y: y
                };
            };

        // 4 暂停阶段 鼠标离开画面 进入该阶段
        // 4.1 敌方飞机 我方飞机以及子弹静止
        canvas.onmouseleave = function () {
    
    
            if (state === RUNNING) {
    
    
                state = PAUSE;
            }
        }
        canvas.onmouseover = function () {
    
    
            if (state === PAUSE) {
    
    
                state = RUNNING;
            }
        }
        // 暂停图片
        var pause = new Image()
        pause.src = "img/game_pause_nor.png";
        // 4.2 鼠标移入画布 游戏结束,恢复到第三阶段

        // 5 我方飞机发生了爆炸 地方飞机静止

        // 定时器
        var timer = setInterval(function () {
    
    
            sky.paint();
            sky.step();

            switch (state) {
    
    
                case START:
                    ctx.drawImage(logo, 0, 0, WIDTH, HEIGHT);
                    break;
                case STARTING:
                    loading.paint();
                    // loading.step()
                    break;
                case RUNNING:
                    hero.paint();
                    // 我方飞机的运动
                    hero.step();
                    // 我方飞机的射击方法
                    hero.shoot();
                    // 子弹的绘制
                    bulletdPaint();
                    // 子弹的运动
                    bulletdStep();
                    // 子弹的删除
                    bulletDel();
                    // 创建敌方飞机
                    enterEnemise();
                    // 绘制敌方飞机
                    enemyPaint();
                    // 绘制敌方飞机的运动
                    enemyStep();
                    // 删除敌方飞机
                    delenemy();
                    // 判断是否撞击
                    hitEnemise();
                    // 绘制分数和生命值
                    scoreText()
                    break;
                case PAUSE:
                    sky.paint(); // 绘制背景
                    sky.step(); // 背景动画
                    // 绘制我放飞机
                    hero.paint();
                    // 子弹的绘制
                    bulletdPaint();
                    // 绘制敌方飞机
                    enemyPaint();
                    // 绘制分数和生命值
                    scoreText();
                    ctx.drawImage(pause, 220, 300)
                    break;
                case GAMEOVER:
                    sky.paint(); // 绘制背景
                    sky.step(); // 背景动画
                    hero.paint();
                    // 子弹的绘制
                    bulletdPaint();
                    // 绘制敌方飞机
                    enemyPaint();
                    // 绘制分数和生命值
                    scoreText();
                    // 游戏结束
                    gameoverfn();

            }

        }, 30)
    </script>
</body>

</html>

猜你喜欢

转载自blog.csdn.net/RoddyLD/article/details/115449608