canvas飞机大战

用Js实现一个好玩的飞机大战,简单!


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <style>
        canvas{
            position: absolute;
            left: 0;
            right: 0;
            top: 0;
            bottom: 0;
            margin: 0 auto;
        }
    </style>
</head>
<body>
<canvas id="canvas" width="512" height="768"></canvas>
<script>
    var canvas = document.getElementById("canvas");
    var context = canvas.getContext("2d");

    // 0  游戏初始化的一些数据
    // 0.1 把上面游戏的五个阶段整理成数字
    const START = 0;
    const STARTTING = 1;
    const RUNNING = 2;
    const PAUSE = 3;
    const GAMEOVER = 4;
    // 0.2 定义一个自己的状态,时刻跟上面的五个状态进行比较,然后判断游戏目前处于哪个阶段
    var state = START;
    // 0.3 画布的信息得获取过来
    const WIDTH = 512;
    const HEIGHT = 768;
    // 0.4 游戏的分数
    var score = 0;
    // 0.5 我方飞机的生命
    var life = 3;
    // 1  第一阶段 游戏欢迎阶段
    // 1.1 加载背景图片
    // 1.1.1  创建背景图片的dom对象
    var bg = new Image();
    bg.src = "img/1.jpg";
    // 1.1.2  背景图片的详细信息(用对象表示)
    var BG = {
        imgs : bg,
        width : 512,
        height : 768
    }
    // 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 abc = new Bg(BG)
    // 1.2 加载LOGO
    var logo = new Image();
    logo.src = "img/start.png";
    // 2  第二阶段 游戏过渡阶段
    // 2.1 创建图片的构造
    var loadings = [];
    loadings[0] = new Image();
    loadings[0].src = "img/game_loading1.png";
    loadings[1] = new Image();
    loadings[1].src = "img/game_loading2.png";
    loadings[2] = new Image();
    loadings[2].src = "img/game_loading3.png";
    loadings[3] = new Image();
    loadings[3].src = "img/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 % 5 == 0){
                this.startIndex ++;
            }
            // 临界点,图片加载完成以后,到第三阶段去
            if(this.startIndex == this.length){
                state = RUNNING;
            }
        }
    }
    // 2.4 动画效果的对象
    var loading = new Loading(LOADINGS);
    // 2.5 onclick
    canvas.onclick = function(){
        if(state == START){
            state = STARTTING;
        }
    }
    // 3  第三阶段 游戏运行中
    // 3.1 绘制我方飞机
    // 3.1.1 加载我方飞机的图片(1.飞机正常运行的状态,2.飞机碰撞以后的状态)
    var heros = [];
    heros[0] = new Image();
    heros[0].src = "img/myhero.png";
    heros[1] = new Image();
    heros[1].src = "img/myhero.png";

    heros[2] = new Image();
    heros[2].src = "img/hero_blowup_n1.png";
    heros[3] = new Image();
    heros[3].src = "img/hero_blowup_n2.png";
    heros[4] = new Image();
    heros[4].src = "img/hero_blowup_n3.png";
    heros[5] = new Image();
    heros[5].src = "img/hero_blowup_n4.png";
    // 3.1.2 初始化我方飞机的数据
    var HEROS = {
        imgs : heros,
        length : heros.length,
        width : 135,
        height : 131,
        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 - 100;
        // 增加一个标识,表示飞机是否发生了碰撞,给个false,表示一直没有碰撞
        this.down = false;
        // 增加一个标识,表示飞机碰撞以后,碰撞的动画,碰撞的动画是否执行完成
        this.candel = false;

        // 绘制方法
        this.paint = function(){
            context.drawImage(this.imgs[this.startIndex],this.x,this.y);
        }
        // 运动方法
        this.step = function(){
            // 监测飞机是否碰撞的属性,如果没有碰撞,索引在0和1之间切换
            if(!this.down){
                // 没有碰撞,切换索引
                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{
                        hero = new Hero(HEROS);
                    }
                }
            }
        }
        this.time = 0;
        //射击方法
        this.shoot = function(){
            this.time ++;
            if(this.time % 4 == 0){
                bullets.push(new Bullet(BULLET));
            }
        }
        this.bang = function(){
            this.down = true;
        }
    }
    // 3.1.4 创建对象
    var hero = new Hero(HEROS);
    // 3.1.5 飞机跟随鼠标移动
    canvas.onmousemove = function(event){
        if(state == RUNNING){
            var x = event.offsetX;
            var y = event.offsetY;
            // 直接赋值给飞机的x和y坐标
            hero.x = x - hero.width/2;
            hero.y = y - hero.height/2;
        }
    }
    // 3.2 绘制子弹
    // 3.2.1 加载子弹的图片
    var bullet = new Image();
    bullet.src = "img/2.png";
    // 3.2.2 初始化子弹的数据
    var BULLET = {
        imgs : bullet,
        width : 19,
        height : 29
    }
    // 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;
        // 撞击的方法,用于修改子弹是否碰撞的属性
        this.bang = function(){
            this.candel = true;
        }
    }
    // 3.2.4 增加一个数组,用来存储子弹
    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(){
        for(var i = 0;i < bullets.length;i++){
            if(bullets[i].y < -bullets[i].height || bullets[i].candel){
                bullets.splice(i,1);
            }
        }
    }
    // 3.3 绘制地方飞机
    // 3.3.1 加载敌方飞机的图片(3种)
    // 小飞机
    var enemy1 = [];
    enemy1[0] = new Image();
    enemy1[0].src = "img/dj1.png";
    enemy1[1] = new Image();
    enemy1[1].src = "img/1.gif";
    // 中飞机
    var enemy2 = [];
    enemy2[0] = new Image();
    enemy2[0].src = "img/dj2.png";
    enemy2[1] = new Image();
    enemy2[1].src = "img/1.gif";
    // 大飞机
    var enemy3 = [];
    enemy3[0] = new Image();
    enemy3[0].src = "img/dj3.png";
    enemy3[1] = new Image();
    enemy3[1].src = "img/dj3.png";
    enemy3[2] = new Image();
    enemy3[2].src = "img/1.gif";
    // 3.3.2 初始化敌方飞机的数据
    var ENEMY1 = {
        imgs : enemy1,
        length : enemy1.length,
        width : 90,
        height : 69,
        type : 1,    //增加一个类型,判断是哪一种飞机
        frame : 1,
        life : 1,
        score : 1
    }
    var ENEMY2 = {
        imgs : enemy2,
        length : enemy2.length,
        width : 152,
        height : 115,
        type : 2,    //增加一个类型,判断是哪一种飞机
        frame : 1,
        life : 5,
        score : 5
    }
    var ENEMY3 = {
        imgs : enemy3,
        length : enemy3.length,
        width : 197,
        height : 134,
        type : 3,    //增加一个类型,判断是哪一种飞机
        frame : 2,
        life : 10,
        score : 10
    }
    // 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;
        // 增加一个标识,表示飞机是否发生了碰撞,给个false,表示一直没有碰撞
        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){
                // 根据飞机的状态来判定飞机是否由动画,就是要大飞机有动画效果
                this.startIndex ++;
                // 小飞机和中飞机就是0,大飞机是在0和1之间切换
                this.startIndex = this.startIndex % this.frame;
                this.y ++;
            }else{
                this.startIndex++;
                if(this.startIndex == this.length){
                    this.candel = true;
                    this.startIndex = this.length - 1;
                }
            }
        }
        this.checkHit = function(zd){   //这个参数可能是子弹,可能是我方飞机
            return zd.y + zd.height > this.y
                && zd.x + zd.width > this.x
                && zd.y < this.y + this.height
                && zd.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 pushEnemies(){
        var numRand = Math.floor(Math.random() * 100);
        if(numRand < 5){
            enemies.push(new Enemy(ENEMY1))
        }else if(numRand > 98){
            enemies.push(new Enemy(ENEMY2))
        }else if(numRand == 50){
            enemies.push(new Enemy(ENEMY3))
        }
    }
    // 3.3.6 敌方飞机的绘制函数
    function paintEnemies(){
        for(var i = 0;i < enemies.length;i++){
            enemies[i].paint()
        }
    }
    // 3.3.7 敌方飞机的运动函数
    function stepEnemies(){
        for(var i = 0;i < enemies.length;i++){
            enemies[i].step()
        }
    }
    // 3.3.8 敌方飞机的删除函数
    function delEnemies(){
        for(var i = 0;i < enemies.length;i++){
            // 两种情况
            if(enemies[i].y > HEIGHT || enemies[i].candel){
                enemies.splice(i,1);
            }
        }
    }
    // 3.4 检测是否撞击
    function hitEnemies(){
        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,20,20);
        context.fillText("LIFE:" + life,300,20);
    }

    // 4  第四阶段 游戏暂停
    canvas.onmouseout = 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";
    // 5  第五阶段 游戏GG
    function paintOver(){
        context.font = "bold 50px 微软雅黑";
        context.fillText("GAME OVER!!!",50,250);
    }





    setInterval(function(){
        abc.paint();
        abc.step();
        switch (state) {
            case START:
                context.drawImage(logo,40,0)
                break;

            case STARTTING:
                loading.paint();
                loading.step();
                break;

            case RUNNING:
                hero.paint();
                hero.step();
                hero.shoot();

                bulletsPaint();
                bulletsStep();
                bulletsDel();

                pushEnemies();
                paintEnemies();
                stepEnemies();
                delEnemies();

                hitEnemies();

                paintText();
                break;

            case PAUSE:
                hero.paint();

                bulletsPaint();

                paintEnemies();

                paintText();

                context.drawImage(pause,246,350);
                break;

            case GAMEOVER:
                hero.paint();

                bulletsPaint();

                paintEnemies();

                paintText();

                paintOver()
                break;

        }
    },10)

</script>
</body>
</html>

1.gif
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

实战效果:
在这里插入图片描述

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值