首页
搜索 搜索
当前位置:首页 > 行业资讯

我的第一个项目(十一) :飞机大战分包完成(简单阐述分包思路以及过程)

2023-04-19 02:10:09 经济日报客户端

好家伙,


(相关资料图)

代码已开源

Git:

https://gitee.com/tang-and-han-dynasties/panghu-planebattle-esm.git

NPM:

panghu-planebattle-esm - npm (npmjs.com)

现在,比如说,我用Vue写好了个人博客主页的前端

我想在这个主页里面加点东西,让我的博客更缤纷多彩一点

我想在他的主页里面塞个小游戏,他会怎么做

1.思考步骤

如下:

第一步:去网上找个小游戏的资源,将这个包下载到本地,

诶,正好发现有个飞机大战 panghu-planebattle-modular小游戏开发好了

我可以直接下载,或者通过npm安装

npm install panghu-planebattle-modular

第二步:导入到某个.vue文件或html文件

通过import导入

第三步:划一个区域

给这个包去渲染游戏

剩下的他就不用管了

大概是这么个过程,然后我们按着这个思路,反向去分我们这个包

先来看看原先的完整代码:

完整代码

    <script>  export default {    mounted() {        //canvas初始化        console.log("我被执行啦")        let canvas = document.createElement("canvas");        this.$refs.stage.appendChild(canvas);        canvas.width = 480;        canvas.height = 650;        canvas.ref = canvas;        canvas.style = "border: 1px solid red;"        const context = canvas.getContext("2d");          //图片初始化方法        function createImage(src) {          let img;          if (typeof src === "string") {            img = new Image();            img.src = require("./img/" + src);          } else {            img = [];            for (let i = 0; i < src.length; i++) {              img[i] = new Image();              img[i].src = require("./img/" + src[i]);            }          }          return img;        }        //createImage()方法测试样例        // let bg = createImage("4.jpg")        // bg.onload = function () {        //   console.log("img加载完毕")        //   context.drawImage(bg, 0, 0, 480, 650)        // }        const IMAGES = {          b: "bullet1.png",          bg: "4.png",          copyright: "shoot_copyright.png",          pause: "game_pause.png",          loading_frame: ["game_loading1.png", "game_loading2.png", "game_loading3.png",            "game_loading4.png"          ],          hero_frame_live: ["hero1.png", "hero2.png"],          hero_frame_death: ["hero_blowup_n1.png", "hero_blowup_n2.png", "hero_blowup_n3.png",            "hero_blowup_n4.png"          ],          e1_live: ["enemy1.png"],          e1_death: ["enemy1_down1.png", "enemy1_down2.png", "enemy1_down3.png", "enemy1_down4.png"],          e2_live: ["enemy2.png"],          e2_death: ["enemy2_down1.png", "enemy2_down2.png", "enemy2_down3.png", "enemy2_down4.png"],          e3_live: ["enemy3_n1.png", "enemy3_n2.png"],          e3_death: ["enemy3_down1.png", "enemy3_down2.png", "enemy3_down3.png", "enemy3_down4.png",            "enemy3_down5.png", "enemy3_down6.png"          ],          c1: "lanqiu.png"        };        //初始化各个图片        const b = createImage(IMAGES.b);        const bg = createImage(IMAGES.bg);        const copyright = createImage(IMAGES.copyright);        const pause = createImage(IMAGES.pause);        const loading_frame = createImage(IMAGES.loading_frame);        const hero_frame = {          live: createImage(IMAGES.hero_frame_live),          death: createImage(IMAGES.hero_frame_death),        };        const e1 = {          live: createImage(IMAGES.e1_live),          death: createImage(IMAGES.e1_death),        };        const e2 = {          live: createImage(IMAGES.e2_live),          death: createImage(IMAGES.e2_death),        };        const e3 = {          live: createImage(IMAGES.e3_live),          death: createImage(IMAGES.e3_death),        };        const c1 = createImage(IMAGES.c1);          //配置项:        // 定义游戏的状态        // 开始        const START = 0;        // 开始时        const STARTING = 1;        // 运行时        const RUNNING = 2;        // 暂停时        const PAUSE = 3;        // 结束时        const END = 4;        // 加载中        const LOADINGING = 5;          //state表示游戏的状态 取值必须是以上的五种状态        let state = LOADINGING;        // hero_frame.addEventListener("load", () => {        //   state = START;        // })          pause.onload = function () {          state = START;          console.log(state)        }          //score 分数变量 life 变量        let score = 0;        let life = 3;          //天空类的配置项        const SKY = {          bg: bg,          width: 480,          height: 650,          speed: 10,        };          // 飞机加载界面的配置项        const LOADING = {          frame: loading_frame,          width: 186,          height: 38,          x: 0,          y: 650 - 38,          speed: 400,        };          // 英雄配置项        const HERO = {          frame: hero_frame,          width: 99,          height: 124,          speed: 100,        };          // 子弹配置项        const BULLET = {          img: b,          width: 9,          height: 21,        };          //小敌机配置项        const E1 = {          type: 1,          width: 57,          height: 51,          life: 10,          score: 1,          frame: e1,          minSpeed: 20,          maxSpeed: 10        };        //中敌机配置项        const E2 = {          type: 2,          width: 69,          height: 95,          life: 50,          score: 5,          frame: e2,          minSpeed: 50,          maxSpeed: 20        };        //打敌机配置项        const E3 = {          type: 3,          width: 169,          height: 258,          life: 100,          score: 20,          frame: e3,          minSpeed: 100,          maxSpeed: 100        };        //奖励类配置项        const C1 = {          type: 4,          width: 75,          height: 75,          life: 1,          score: 1,          img: c1,          minSpeed: 5,          maxSpeed: 10        };        //正式代码          //初始化奖励类        class Award {          constructor(config) {            this.type = config.type;            this.width = config.width;            this.height = config.height;            this.x = Math.floor(Math.random() * (480 - config.width));            this.y = -config.height;            this.life = config.life;            this.score = config.score;            this.img = config.img;            this.live = true;            this.speed = Math.floor(Math.random() * (config.minSpeed - config.maxSpeed + 1)) + config.maxSpeed;            this.lastTime = new Date().getTime();            this.deathIndex = 0;            this.destory = false;          }          move() {            const currentTime = new Date().getTime();            if (currentTime - this.lastTime >= this.speed) {              if (this.live) {                this.y = this.y + 6;                this.lastTime = currentTime;              } else {                this.destory = true;                }            }          }          paint(context) {            context.drawImage(this.img, this.x, this.y, this.width, this.height);          }          outOfBounds() {            if (this.y > 650) {              return true;            }          }          hit(o) {            let ol = o.x;            let or = o.x + o.width;            let ot = o.y;            let ob = o.y + o.height;            let el = this.x;            let er = this.x + this.width;            let et = this.y;            let eb = this.y + this.height;            if (ol > er || or < el || ot > eb || ob < et) {              return false;            } else {              return true;            }          }          // collide() {          //   this.life--;          //   if (this.life === 0) {          //     this.live = false;          //     score += this.score;          //   }          // }        }          //        //初始化一个子弹类        class Bullet {          constructor(config, x, y) {            this.img = config.img;            this.width = config.width;            this.height = config.height;            this.x = x;            this.y = y;            this.destory = false;          }          //子弹绘制方法          paint(context) {            context.drawImage(this.img, this.x, this.y);          }          //移动子弹 this.y--          move() {            this.y -= 8;          }          outOfBounds() {            //如果返回的是真的话 那么我们应该销毁掉这个子弹            return this.y < -this.height;          }          collide() {            //让这颗子弹变成可销毁状态            this.destory = true;          }        }        //          // 初始化一个敌机类        class Enemy {                              constructor(config) {            this.type = config.type;            this.width = config.width;            this.height = config.height;            this.x = Math.floor(Math.random() * (480 - config.width));            this.y = -config.height;            this.life = config.life;            this.score = config.score;            this.frame = config.frame;            this.img = this.frame.live[0];            this.live = true;            this.speed = Math.floor(Math.random() * (config.minSpeed - config.maxSpeed + 1)) + config.maxSpeed;            this.lastTime = new Date().getTime();            this.deathIndex = 0;            this.destory = false;          }          move() {            const currentTime = new Date().getTime();            if (currentTime - this.lastTime >= this.speed) {              if (this.live) {                this.img = this.frame.live[0];                this.y++;                this.lastTime = currentTime;              } else {                this.img = this.frame.death[this.deathIndex++];                if (this.deathIndex === this.frame.death.length) {                  this.destory = true;                }              }            }          }          paint(context) {            context.drawImage(this.img, this.x, this.y);          }          outOfBounds() {            if (this.y > 650) {              return true;            }          }          hit(o) {            let ol = o.x;            let or = o.x + o.width;            let ot = o.y;            let ob = o.y + o.height;            let el = this.x;            let er = this.x + this.width;            let et = this.y;            let eb = this.y + this.height;            if (ol > er || or < el || ot > eb || ob < et) {              return false;            } else {              return true;            }          }          collide() {            this.life--;            if (this.life === 0) {              this.live = false;              score += this.score;            }          }        }          //        // 初始化一个英雄类        class Hero {          constructor(config) {            this.width = config.width;            this.height = config.height;            this.x = (480 - config.width) / 2;            this.y = 650 - config.height;            this.frame = config.frame;            this.frameLiveIndex = 0;            this.frameDeathIndex = 0;            this.lastTime = new Date().getTime();            this.speed = config.speed;            //当前展示的图片            this.img = null;            this.live = true;            //子弹上次射击的时间            this.lastShootTime = new Date().getTime();            //子弹射击的间隔            this.shootInterval = 50;            //子弹夹数组            this.bulletList = [];            this.destory = false;          }          judge() {            const currentTime = new Date().getTime();            if (currentTime - this.lastTime > this.speed) {              if (this.live) {                this.img = this.frame.live[this.frameLiveIndex++ % this.frame.live.length];              } else {                //0 1 2 3 4                this.img = this.frame.death[this.frameDeathIndex++];                //到4的时候英雄死了                if (this.frameDeathIndex === this.frame.death.length) {                  this.destory = true;                }              }              this.lastTime = currentTime;            }          }          paint(context) {            context.drawImage(this.img, this.x, this.y, this.width, this.height);          }          //英雄可以射击子弹          shoot() {            //获取当前时间            const currentTime = new Date().getTime();            //飞机的位置            if (currentTime - this.lastShootTime > this.shootInterval) {              //在飞机的头部初始化一个子弹对象              let bullet = new Bullet(BULLET, this.x + this.width / 2 - BULLET.width / 2, this.y - BULLET.height);              //英雄飞机要认领这个子弹              this.bulletList.push(bullet);              //在网页上绘制一个子弹对象              bullet.paint(context);              //更新英雄射击时间              this.lastShootTime = currentTime;            }          }          collide() {            //将活着标识符切换为false            //活着 -> 爆炸中 -> 死亡(销毁)            this.live = false;          }        }        //        // 初始化一个飞机界面加载类        class Loading {          constructor(config) {            this.frame = config.frame;            this.frameIndex = 0;            this.width = config.width;            this.height = config.height;            this.x = config.x;            this.y = config.y;            this.speed = config.speed;            this.lastTime = new Date().getTime();          }          judge() {            const currentTime = new Date().getTime();            if (currentTime - this.lastTime > this.speed) {              this.frameIndex++;              if (this.frameIndex === 4) {                state = RUNNING;              }              this.lastTime = currentTime;            }          }          paint(context) {            context.drawImage(this.frame[this.frameIndex], this.x, this.y);          }        }            class Main {          //一下全为全局变量或方法 (全局的!!)          //初始化一个天空实例          //主启动方法          maingame() {            const sky = new Sky(SKY);            //初始化一个飞机界面加载实例            const loading = new Loading(LOADING);            //初始化一个英雄实例 英雄是会变的            let hero = new Hero(HERO);            //该变量中有所有的敌机实例            let enemies = [];            //该变量中存放所有的奖励实例              let awards = [];            //敌机产生的速率            let ENEMY_CREATE_INTERVAL = 800;            let ENEMY_LASTTIME = new Date().getTime();              function stateControl() {              //为canvas绑定一个点击事件 且他如果是START状态的时候需要修改成STARTING状态              canvas.addEventListener("click", () => {                if (state === START) {                  state = STARTING;                }              });              // 为canvas绑定一个鼠标移动事件 鼠标正好在飞机图片的正中心              canvas.addEventListener("mousemove", (e) => {                let x = e.offsetX;                let y = e.offsetY;                hero.x = x - hero.width / 2;                hero.y = y - hero.height / 2;              });              // 为canvas绑定一个鼠标离开事件 鼠标离开时 RUNNING -> PAUSE              canvas.addEventListener("mouseleave", () => {                if (state === RUNNING) {                  state = PAUSE;                }              });              // 为canvas绑定一个鼠标进入事件 鼠标进入时 PAUSE => RUNNING              canvas.addEventListener("mouseenter", () => {                if (state === PAUSE) {                  state = RUNNING;                }              });              //为canvas绑定一个屏幕移动触摸点事件 触碰点正好在飞机图片的正中心              canvas.addEventListener("touchmove", (e) => {                // let x = e.pageX;                // let y = e.pageY;                console.log(e);                // let x = e.touches[0].clientX;                // let y = e.touches[0].clinetY;                let x = e.touches[0].pageX;                let y = e.touches[0].pageY;                // let x = e.touches[0].screenX;                // let y = e.touches[0].screenY;                let write1 = (document.body.clientWidth - 480) / 2;                let write2 = (document.body.clientHeight - 650) / 2;                hero.x = x - write1 - hero.width / 2;                hero.y = y - write2 - hero.height / 2;                  // hero.x = x - hero.width / 2;                // hero.y = y - hero.height / 2;                console.log(x, y);                console.log(document.body.clientWidth, document.body.clientHeight);                e.preventDefault(); // 阻止屏幕滚动的默认行为                })            }            stateControl();            // 碰撞检测函数            //此处的碰撞检测包括             //1.子弹与敌机的碰撞            //2.英雄与敌机的碰撞            //3.英雄与随机奖励的碰撞            function checkHit() {              // 遍历所有的敌机              for (let i = 0; i < awards.length; i++) {                //检测英雄是否碰到奖励类                if (awards[i].hit(hero)) {                  //当然了,这个随机奖励的样式也要删了                  awards.splice(i, 1);                  //清除所有的敌机                  // for (let i = 0; i < enemies.length; i++) {                  //   enemies.splice(i, 1);                  // }                  enemies.length = 0;                  }              }              for (let i = 0; i < enemies.length; i++) {                //检测英雄是否撞到敌机                if (enemies[i].hit(hero)) {                  //将敌机和英雄的destory属性改为true                  enemies[i].collide();                  hero.collide();                }                for (let j = 0; j < hero.bulletList.length; j++) {                  enemies[i].hit(hero.bulletList[j]);                  //检测子弹是否撞到敌机                  if (enemies[i].hit(hero.bulletList[j])) {                    //将敌机和子弹的destory属性改为true                    enemies[i].collide();                    hero.bulletList[j].collide();                  }                }              }            }            // 全局函数 隔一段时间就来初始化一架敌机/奖励            function createComponent() {              const currentTime = new Date().getTime();              if (currentTime - ENEMY_LASTTIME >= ENEMY_CREATE_INTERVAL) {                let ran = Math.floor(Math.random() * 100);                if (ran < 55) {                  enemies.push(new Enemy(E1));                } else if (ran < 85 && ran > 55) {                  enemies.push(new Enemy(E2));                } else if (ran < 95 && ran > 85) {                  enemies.push(new Enemy(E3));                } else if (ran > 95) {                  awards.push(new award(C1));                  }                  ENEMY_LASTTIME = currentTime;              }            }            // 全局函数 来判断所有的子弹/敌人组件 "负责移动"            function judgeComponent() {              for (let i = 0; i < hero.bulletList.length; i++) {                hero.bulletList[i].move();              }              for (let i = 0; i < enemies.length; i++) {                enemies[i].move();              }              for (let i = 0; i < awards.length; i++) {                awards[i].move();              }            }            // 全局函数 来绘制所有的子弹/敌人组件 绘制score&life面板            function paintComponent() {              for (let i = 0; i < hero.bulletList.length; i++) {                hero.bulletList[i].paint(context);              }              for (let i = 0; i < enemies.length; i++) {                enemies[i].paint(context);              }              for (let i = 0; i < awards.length; i++) {                awards[i].paint(context);              }              context.font = "20px 微软雅黑";              context.fillStyle = "green";              context.textAlign = "left";              context.fillText("score: " + score, 10, 20);              context.textAlign = "right";              context.fillText("life: " + life, 480 - 10, 20);              //重置样式              context.fillStyle = "black";              context.textAlign = "left";            }            // 全局函数 来销毁所有的子弹/敌人组件 销毁掉英雄            function deleteComponent() {              if (hero.destory) {                life--;                hero.destory = false;                if (life === 0) {                  state = END;                } else {                  hero = new Hero(HERO);                }              }              for (let i = 0; i < hero.bulletList.length; i++) {                if (hero.bulletList[i].outOfBounds() || hero.bulletList[i].destory) {                  hero.bulletList.splice(i, 1);                }              }              for (let i = 0; i < enemies.length; i++) {                if (enemies[i].outOfBounds() || enemies[i].destory) {                  enemies.splice(i, 1);                }              }            }              //当图片加载完毕时,需要做某些事情            bg.addEventListener("load", () => {              setInterval(() => {                switch (state) {                  case START:                    sky.judge();                    sky.paint(context);                    let logo_x = (480 - copyright.naturalWidth) / 2;                    let logo_y = (650 - copyright.naturalHeight) / 2;                    context.drawImage(copyright, logo_x, logo_y);                    break;                  case STARTING:                    sky.judge();                    sky.paint(context);                    loading.judge();                    loading.paint(context);                    break;                  case RUNNING:                    sky.judge();                    sky.paint(context);                    hero.judge();                    hero.paint(context);                    hero.shoot();                    createComponent();                    judgeComponent();                    deleteComponent();                    paintComponent();                    checkHit();                    break;                  case PAUSE:                    let pause_x = (480 - pause.naturalWidth) / 2;                    let pause_y = (650 - pause.naturalHeight) / 2;                    context.drawImage(pause, pause_x, pause_y);                    break;                  case END:                    //给我的画笔设置一个字的样式                    //后面写出来的字都是这个样式的                    context.font = "bold 24px 微软雅黑";                    context.textAlign = "center";                    context.textBaseline = "middle";                    context.fillText("GAME_OVER", 480 / 2, 650 / 2);                    break;                }              }, 10);            });                //背景切换方法            // function changebg() {            //     console.log("changebg方法被触发")            //     bg.src = "img/background.png"            // }          }        }        //          //初始化一个天空类        class Sky {          constructor(config) {            this.bg = config.bg;            this.width = config.width;            this.height = config.height;            this.x1 = 0;            this.y1 = 0;            this.x2 = 0;            this.y2 = -this.height;            this.speed = config.speed;            this.lastTime = new Date().getTime();          }          //判断方法          judge() {            let currentTime = new Date().getTime();            if (currentTime - this.lastTime > this.speed) {              this.y1++;              this.y2++;              this.lastTime = currentTime;            }            if (this.y2 === 0) {              this.y1 = 0;              this.y2 = -this.height;            }          }          //绘图方法          paint(context) {            context.drawImage(this.bg, this.x1, this.y1, this.width, this.height);            context.drawImage(this.bg, this.x2, this.y2, this.width, this.height);          }        }        let main_1 = new Main()        main_1.maingame();      }    }      </script>        
Helloworld.vue

一看,738行,这,没人想维护的,复制粘贴都嫌累

(再看一眼就要爆炸)

我们要实现一个这样的效果(事实上也实现了)

<script>import { canvas, main_1 } from "panghu-planebattle-modular"export default {  mounted() {    this.$refs.stage.appendChild(canvas);    main_1.maingame();  }}</script>

而事实上,就是三行代码:

//从包中导入canvas,main_1import { canvas, main_1 } from "panghu-planebattle-modular"//dom操作添加canvasthis.$refs.stage.appendChild(canvas); //调用main_1的maingame方法main_1.maingame();

让使用者操作的部分由738行代码变成3行代码

2.开始分包

将程序主要分成下面几个需要处理的部分

1、静态的:图片,图片地址,配置项

2、六个小类:Enemy、Hero、Loading、Sky、Award、Bullet

3、主启动类:Main

4、全局方法,全局变量

5、入口(对外导出的对象)

项目目录结构如下:

1.图片

2.配置项

首先是配置项config.js

我们将所有的配置项文件都放在这里,全局变量也放在这里

如果将来我们要调参数,比如说,改改图片,改改子弹的速度之类,就直接在这个文件里改就行了

3.其中六个小类,我把他们"独立"分开

比如Bullet(子弹类)

//初始化一个子弹类class Bullet {  constructor(config, x, y) {    this.img = config.img;    this.width = config.width;    this.height = config.height;    this.x = x;    this.y = y;    this.destory = false;  }  //子弹绘制方法  paint(context) {    context.drawImage(this.img, this.x, this.y);  }  //移动子弹 this.y--  move() {    this.y -= 8;  }  outOfBounds() {    //如果返回的是真的话 那么我们应该销毁掉这个子弹    return this.y < -this.height;  }  collide() {    //让这颗子弹变成可销毁状态    this.destory = true;  }}export default Bullet 

这里需要提一嘴的是,类的导出必须带 default,否则会报错

export default Bullet 

4.主启动类main

我们将所有曾经的全局方法,还有定时器都封装到这个类中

最后新建一个实例,并导出

1 import Enemy from "./enemy"  2 import Hero from "./hero"  3 import Loading from "./loading"  4 import Sky from "./sky"  5 import Award from "./award"  6   7 import { START, STARTING, RUNNING, PAUSE, END } from "./config"  8 import { SKY, LOADING, HERO, E1, E2, E3, C1 } from "./config"  9 import { bg, copyright, pause } from "./config" 10 import { canvas, context } from "./config" 11  12 class Main { 13     //以下全为全局变量或方法 (全局的!!) 14     //初始化一个天空实例 15     //主启动方法 16     maingame() { 17         const sky = new Sky(SKY); 18         //初始化一个飞机界面加载实例 19         const loading = new Loading(LOADING); 20         //初始化一个英雄实例 英雄是会变的 21         let hero = new Hero(HERO); 22         //该变量中有所有的敌机实例 23         let enemies = []; 24         //该变量中存放所有的奖励实例 25         let awards = []; 26         //敌机产生的速率 27         let ENEMY_CREATE_INTERVAL = 800; 28         let ENEMY_LASTTIME = new Date().getTime(); 29  30         function stateControl() { 31             //为canvas绑定一个点击事件 且他如果是START状态的时候需要修改成STARTING状态 32             canvas.addEventListener("click", () => { 33                 if (state === START) { 34                     state = STARTING; 35                 } 36             }); 37             // 为canvas绑定一个鼠标移动事件 鼠标正好在飞机图片的正中心 38             canvas.addEventListener("mousemove", (e) => { 39                 let x = e.offsetX; 40                 let y = e.offsetY; 41                 hero.x = x - hero.width / 2; 42                 hero.y = y - hero.height / 2; 43             }); 44             // 为canvas绑定一个鼠标离开事件 鼠标离开时 RUNNING -> PAUSE 45             canvas.addEventListener("mouseleave", () => { 46                 if (state === RUNNING) { 47                     state = PAUSE; 48                 } 49             }); 50             // 为canvas绑定一个鼠标进入事件 鼠标进入时 PAUSE => RUNNING 51             canvas.addEventListener("mouseenter", () => { 52                 if (state === PAUSE) { 53                     state = RUNNING; 54                 } 55             }); 56             //为canvas绑定一个屏幕移动触摸点事件 触碰点正好在飞机图片的正中心 57             canvas.addEventListener("touchmove", (e) => { 58                 // let x = e.pageX; 59                 // let y = e.pageY; 60                 console.log(e); 61                 // let x = e.touches[0].clientX; 62                 // let y = e.touches[0].clinetY; 63                 let x = e.touches[0].pageX; 64                 let y = e.touches[0].pageY; 65                 // let x = e.touches[0].screenX; 66                 // let y = e.touches[0].screenY; 67                 let write1 = (document.body.clientWidth - 480) / 2; 68                 let write2 = (document.body.clientHeight - 650) / 2; 69                 hero.x = x - write1 - hero.width / 2; 70                 hero.y = y - write2 - hero.height / 2; 71  72                 // hero.x = x - hero.width / 2; 73                 // hero.y = y - hero.height / 2; 74                 console.log(x, y); 75                 console.log(document.body.clientWidth, document.body.clientHeight); 76                 e.preventDefault(); // 阻止屏幕滚动的默认行为 77  78             }) 79         } 80         stateControl(); 81         // 碰撞检测函数 82         //此处的碰撞检测包括  83         //1.子弹与敌机的碰撞 84         //2.英雄与敌机的碰撞 85         //3.英雄与随机奖励的碰撞 86         function checkHit() { 87             // 遍历所有的敌机 88             for (let i = 0; i < awards.length; i++) { 89                 //检测英雄是否碰到奖励类 90                 if (awards[i].hit(hero)) { 91                     //当然了,这个随机奖励的样式也要删了 92                     awards.splice(i, 1); 93                     //清除所有的敌机 94                     // for (let i = 0; i < enemies.length; i++) { 95                     //   enemies.splice(i, 1); 96                     // } 97                     enemies.length = 0; 98  99                 }100             }101             for (let i = 0; i < enemies.length; i++) {102                 //检测英雄是否撞到敌机103                 if (enemies[i].hit(hero)) {104                     //将敌机和英雄的destory属性改为true105                     enemies[i].collide();106                     hero.collide();107                 }108                 for (let j = 0; j < hero.bulletList.length; j++) {109                     enemies[i].hit(hero.bulletList[j]);110                     //检测子弹是否撞到敌机111                     if (enemies[i].hit(hero.bulletList[j])) {112                         //将敌机和子弹的destory属性改为true113                         enemies[i].collide();114                         hero.bulletList[j].collide();115                     }116                 }117             }118         }119         // 全局函数 隔一段时间就来初始化一架敌机/奖励120         function createComponent() {121             const currentTime = new Date().getTime();122             if (currentTime - ENEMY_LASTTIME >= ENEMY_CREATE_INTERVAL) {123                 let ran = Math.floor(Math.random() * 100);124                 if (ran < 55) {125                     enemies.push(new Enemy(E1));126                 } else if (ran < 85 && ran > 55) {127                     enemies.push(new Enemy(E2));128                 } else if (ran < 95 && ran > 85) {129                     enemies.push(new Enemy(E3));130                 } else if (ran > 95) {131                     awards.push(new Award(C1));132 133                 }134 135                 ENEMY_LASTTIME = currentTime;136             }137         }138         // 全局函数 来判断所有的子弹/敌人组件 "负责移动"139         function judgeComponent() {140             for (let i = 0; i < hero.bulletList.length; i++) {141                 hero.bulletList[i].move();142             }143             for (let i = 0; i < enemies.length; i++) {144                 enemies[i].move();145             }146             for (let i = 0; i < awards.length; i++) {147                 awards[i].move();148             }149         }150         // 全局函数 来绘制所有的子弹/敌人组件 绘制score&life面板151         function paintComponent() {152             for (let i = 0; i < hero.bulletList.length; i++) {153                 hero.bulletList[i].paint(context);154             }155             for (let i = 0; i < enemies.length; i++) {156                 enemies[i].paint(context);157             }158             for (let i = 0; i < awards.length; i++) {159                 awards[i].paint(context);160             }161             context.font = "20px 微软雅黑";162             context.fillStyle = "green";163             context.textAlign = "left";164             context.fillText("score: " + score, 10, 20);165             context.textAlign = "right";166             context.fillText("life: " + life, 480 - 10, 20);167             //重置样式168             context.fillStyle = "black";169             context.textAlign = "left";170         }171         // 全局函数 来销毁所有的子弹/敌人组件 销毁掉英雄172         function deleteComponent() {173             if (hero.destory) {174                 life--;175                 hero.destory = false;176                 if (life === 0) {177                     state = END;178                 } else {179                     hero = new Hero(HERO);180                 }181             }182             for (let i = 0; i < hero.bulletList.length; i++) {183                 if (hero.bulletList[i].outOfBounds() || hero.bulletList[i].destory) {184                     hero.bulletList.splice(i, 1);185                 }186             }187             for (let i = 0; i < enemies.length; i++) {188                 if (enemies[i].outOfBounds() || enemies[i].destory) {189                     enemies.splice(i, 1);190                 }191             }192         }193 194         //当图片加载完毕时,需要做某些事情195         bg.addEventListener("load", () => {196             setInterval(() => {197                 switch (state) {198                     case START:199                         sky.judge();200                         sky.paint(context);201                         let logo_x = (480 - copyright.naturalWidth) / 2;202                         let logo_y = (650 - copyright.naturalHeight) / 2;203                         context.drawImage(copyright, logo_x, logo_y);204                         break;205                     case STARTING:206                         sky.judge();207                         sky.paint(context);208                         loading.judge();209                         loading.paint(context);210                         break;211                     case RUNNING:212                         sky.judge();213                         sky.paint(context);214                         hero.judge();215                         hero.paint(context);216                         hero.shoot(context);217                         createComponent();218                         judgeComponent();219                         deleteComponent();220                         paintComponent();221                         checkHit();222                         break;223                     case PAUSE:224                         let pause_x = (480 - pause.naturalWidth) / 2;225                         let pause_y = (650 - pause.naturalHeight) / 2;226                         context.drawImage(pause, pause_x, pause_y);227                         break;228                     case END:229                         //给我的画笔设置一个字的样式230                         //后面写出来的字都是这个样式的231                         context.font = "bold 24px 微软雅黑";232                         context.textAlign = "center";233                         context.textBaseline = "middle";234                         context.fillText("GAME_OVER", 480 / 2, 650 / 2);235                         break;236                 }237             }, 10);238         });239 240 241         //背景切换方法242         // function changebg() {243         //     console.log("changebg方法被触发")244         //     bg.src = "img/background.png"245         // }246     }247 }248 export let main_1 = new Main()249 // export default Main 
main.js

5.包的入口

首先看一眼package.json

看main,(这个可以自己调的)

由上图可知,这个包的入口就是index.js了

//index.jsexport { canvas } from "./config"export { main_1 } from "./main"

config.js中的canvas

export let canvas = document.createElement("canvas");canvas.width = 480;canvas.height = 650;canvas.ref = canvas;canvas.style = "border: 1px solid red;"

main.js中的main

export let main_1 = new Main()

在这里,用上我们前几天学的语法(嘿嘿)

分包完成