好家伙,
代码已开源
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导入
第三步:划一个区域<div>给这个包去渲染游戏
剩下的他就不用管了
大概是这么个过程,然后我们按着这个思路,反向去分我们这个包
先来看看原先的完整代码:
完整代码
<template> <div> <h1>欢迎来到主页面</h1> <div ref="stage"></div> </div> </template> <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> <style> #stage { width: 480px; height: 650px; margin: 0 auto; } </style>Helloworld.vue
一看,738行,这,没人想维护的,复制粘贴都嫌累
(再看一眼就要爆炸)
我们要实现一个这样的效果(事实上也实现了)
<template> <div> <div ref="stage"></div> </div> </template> <script> import { canvas, main_1 } from "panghu-planebattle-modular" export default { mounted() { this.$refs.stage.appendChild(canvas); main_1.maingame(); } } </script> <style> #stage { width: 480px; height: 650px; margin: 0 auto; } </style>
而事实上,就是三行代码:
//从包中导入canvas,main_1 import { canvas, main_1 } from "panghu-planebattle-modular" //dom操作添加canvas this.$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属性改为true 105 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属性改为true 113 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 Mainmain.js
5.包的入口
首先看一眼package.json
看main,(这个可以自己调的)
由上图可知,这个包的入口就是index.js了
//index.js export { 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()
在这里,用上我们前几天学的语法(嘿嘿)
分包完成
标签:阐述,hero,canvas,大战,let,分包,context,height,config From: https://www.cnblogs.com/FatTiger4399/p/17322997.html