我的第一个项目(十) :处理全局变量(解决模块化后变量无法获取的问题)

第一个,项目,处理,全局变量,解决,模块化,变量,无法,获取,问题 · 浏览次数 : 31

小编点评

**问题:** 在使用模块化导入时,`Loading`类被正确加载并初始化,但由于其全局变量 `life` 和 `score` 在 `helloworld.vue` 中被定义为局部变量,模块化导入会导致这些全局变量被覆盖。 **解决方案:** 1. 在 `helloworld.vue` 中定义 `life` 和 `score` 的全局变量。 ```js // helloworld.vue let life = 3; let score = 0; ``` 2. 在 `Loading` 类中使用模块化导入时,将 `life` 和 `score` 的定义移到 `helloworld.vue` 中。 ```js // Loading.js import { life, score } from './config'; ``` 3. 在 `paint` 方法中,使用 `window` 对象访问全局变量并将其作为参数传递。 ```js // Loading.js export default { 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); } }; ``` **修改后的代码:** **helloworld.vue** ```js let life = 3; let score = 0;
``` **Loading.js** ```js import { life, score } from './config'; export default { 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); } }; ```

正文

好家伙,

 

飞机大战分包分的差不多了,

但是又出现了问题:

文件目录如下:

 

然而关于变量

 

 

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

 

来看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;

 

搞定,不报错了

 

与我的第一个项目(十) :处理全局变量(解决模块化后变量无法获取的问题)相似的内容:

我的第一个项目(十) :处理全局变量(解决模块化后变量无法获取的问题)

好家伙, 飞机大战分包分的差不多了, 但是又出现了问题: 文件目录如下: 然而关于变量 helloworld.vue完整代码

我的第一个项目(六):(前后端)密码校验

好家伙, xdm,密码验证忘写了,哈哈 bug展示: 1.登陆没有密码验证 主要体现为,乱输也能登进去 (小问题) 要是这么上线估计直接寄了 分析一波密码校验怎么做: 前端输完用户名密码之后,将数据发送到后端处理 后端要做以下几件事 ①先确认这个用户名已注册 ②我们拿着这个用户名去数据库中找对应的数

聊聊 JSON Web Token (JWT) 和 jwcrypto 的使用

哈喽大家好,我是咸鱼。 最近写的一个 Python 项目用到了 jwcrypto 这个库,这个库是专门用来处理 JWT 的,JWT 全称是 JSON Web Token ,JSON 格式的 Token。 今天就来简单入门一下 JWT。 官方介绍:https://jwt.io/introduction

前后端分离项目(十):实现"改"功能(前后端)

好家伙,本篇介绍如何实现"改" 我们先来看看效果吧 (这可不是假数据哟,这是真数据哟) (忘记录鼠标了,这里是点了一下刷新) First Of All 我们依旧先来理一下思路: 首先在"管理"页面中,我能看到所有的书本信息, 随后,在每一个信息后都有对应的"修改按钮" 当我点击这个按钮时,我要①拿到

我的第一个项目(二):使用Vue做一个登录注册界面

好家伙, 顶不住了,太多的bug, 本来是想把背景用canvas做成动态的,但是,出现了各种问题 为了不耽误进度,我们先把一个简单的登录注册界面做出来 来看看效果: (看上去还不错) 本界面使用Vue2(新建项目的时候记得把less勾上,项目里有用到) 1.项目目录: 2.MyLogin.vue组件

我的第一个项目(三):注册登陆功能(后端)

好家伙,前端出了点bug 我们来搞定后端先: 后端我们用的框架是Spring boot 数据库:MySQl 代码已开源,连接在最后 新建项目: 只点Java Web 项目目录如下: 1.首先,我们在pom.xml文件中导入第三方包: web服务,mysql连接驱动等一系列包 pom.xml文件: <

我的第一个项目(四):(前端)发送请求以及表单校验

好家伙,本篇将继续完善前端界面 效果展示: 1.注册登陆 (后端已启动) 2.注册表单验证 (前端实现的表单验证) 在此之前: 我的第一个项目(二):使用Vue做一个登录注册界面 - 养肥胖虎 - 博客园 (cnblogs.com) 后端部分: 我的第一个项目(三):注册登陆功能(后端) - 养肥胖

我的第一个项目(五):(前后端)注册用户名查重

好家伙, bug终究还是来了,而且是很离谱的bug 来吧,发现问题,再解决问题 1.注册无法检测到用户名重复 也就是说一个用户名可无限注册, 来看bug(。。。) (看来是后端验证逻辑出了问题) 要是这么上线估计直接寄了 2.完成注册用户名查重 大概率是后端出了问题 这里我们先去看看后端,从后端去改

我的第一个项目(七):(解决问题)Vue中canvas无法绘制图片

好家伙, 现在,我想要把我的飞机大战塞到我的主页里去,想办法把文件导入 然后,直接死在第一步,图片渲染都成问题 先用vue写一个测试文件 来测试canvas的绘制

我的第一个项目(八):(解决问题)图片资源无法加载(Error: Cannot find module "../../xxx" )

好家伙,问题一堆 先开一个测试页模拟游戏模块的运行 原先的图片初始化方法失效了,(vue里面自然是用不了这种方法的) function createImage(src) { let img; if (typeof src "string") { img = new Image(); img.src