好家伙,
飞机大战分包分的差不多了,
但是又出现了问题:
文件目录如下:
然而关于变量
helloworld.vue完整代码
<template> <div> <div ref="stage"></div> </div> </template> <script> // Award, // Bullet, // Enemy, // Hero, // Loading, // Main, // Sky //七个大类引进来 import Award from "./js/award" import Bullet from "./js/bullet" import Enemy from "./js/enemy" import Hero from "./js/hero" import Loading from "./js/loading" // import Main from "./js/main" import Sky from "./js/sky" // import SKYY from "./js/config" import { START, STARTING, RUNNING, PAUSE, END, LOADINGING } from "./js/config" import { SKY, LOADING, HERO, BULLET, E1, E2, E3, C1 } from "./js/config" import { bg, copyright, pause } from "./js/config" export default { mounted() { //console测试 console.log("模块化测试") //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"); //state表示游戏的状态 取值必须是以上的五种状态 let state = START; //score 分数变量 life 变量 let score = 0; let life = 3; //初始化奖励类 // class Loading { // constructor(config) { // this.frame = config.frame; // this.img = this.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) { // if (this.frameIndex < 3) // context.drawImage(this.img[this.frameIndex], this.x, this.y); // } // } class Main { //一下全为全局变量或方法 (全局的!!) //初始化一个天空实例 //主启动方法 maingame() { const sky = new Sky(SKY); //初始化一个飞机界面加载实例 const loading = new Loading(LOADING); loading.prototype =this; //初始化一个英雄实例 英雄是会变的 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(context); 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); }); } } let main_1 = new Main() main_1.maingame(); } } </script> <style> #stage { width: 480px; height: 650px; margin: 0 auto; } </style>复制
来看helloworld.vue中的部分代码
import Loading from "./js/loading" /** * * **/ let state = START; const loading = new Loading(LOADING); /** * * **/ loading.judge();复制
loading.js
// import { state } from "./config" // 初始化一个飞机界面加载类 import { RUNNING } from "./config"; class Loading { constructor(config) { this.frame = config.frame; this.img = this.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) { if (this.frameIndex < 3) { context.drawImage(this.img[this.frameIndex], this.x, this.y); } } } export default Loading复制
若我把Loading这个类写在Helloworld.vue中,是不会有报错的,
但我把Loading这个类写在外部的.js文件,然后再使用模块化导入,
可见,es6模块化把原先的作用域分隔开了
那么这个问题怎么解决呢?
同时我还有另外两个全局变量life(生命值)和score(分数)要处理
//state表示游戏的状态 取值必须是以上的五种状态 let state = START; //score 分数变量 life 变量 let score = 0; let life = 3;复制
只能委屈一下window了,把他们都变成全局变量
//state表示游戏的状态 取值必须是以上的五种状态 window.state = START; //score 分数变量 life 变量 window.score = 0; window.life = 3;复制
搞定,不报错了
前言 前段时间跟一位前辈聊到前端职业发展该怎么去规划这个问题。他说到的其中几个点我觉得非常好: 第一是要有清晰的自我认知,知道自己在一个团队或者在一个项目中能发挥怎样的价值,不骄傲自大也不要妄自菲薄;