我的第一个项目(十) :处理全局变量(解决模块化后变量无法获取的问题)
好家伙,
飞机大战分包分的差不多了,
但是又出现了问题:
文件目录如下:
然而关于变量
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;
搞定,不报错了