zoukankan      html  css  js  c++  java
  • 【默默努力】h5-game-heroVSmonster

    先放下作者大大的项目地址:https://github.com/yangyunhe369/h5-game-heroVSmonster
    然后游戏的效果为
    截动图的按键与游戏按键应该冲突,我就截几张图片了。



    接下来我们来分析代码
    页面入口文件,canvas绘制页面背景以及各个图片

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <title>英雄大战小怪兽v1.0</title>
      <link rel="stylesheet" href="css/common.css">
      <link rel="stylesheet" href="css/style.css">
    </head>
    <body>
    <canvas id="canvas" width="1000" height="500"></canvas>
    <div>
      空格键开始游戏<br>
      W、S、A、D键 和 上下左右方向键分别控制英雄、怪兽移动<br>
      K 键、小键盘数字 5 键分别控制英雄和怪兽攻击,P 键暂停游戏
    </div>
    <script src="js/common.js"></script>
    <script src="js/scene.js"></script>
    <script src="js/game.js"></script>
    <script src="js/main.js"></script>
    </body>
    </html>
    

    common.js中是公共的会用到的图片

    //common.js
    /* by:弦云孤赫——David Yang
    ** github - https://github.com/yangyunhe369
    */
    // 封装打印日志方法
    const log = console.log.bind(console)
    // 生成图片对象方法
    const imageFromPath = function (src) {
      let img = new Image()
      img.src = './images/' + src
      return img
    }
    // 图片素材路径
    const allImg = {
      bg: 'gameBg.jpg',
      hero: {
        idle: [ // 站立不动
          'hero-Idle/hero_Idle_0.png',
          'hero-Idle/hero_Idle_1.png',
          'hero-Idle/hero_Idle_2.png',
          'hero-Idle/hero_Idle_3.png',
          'hero-Idle/hero_Idle_4.png',
          'hero-Idle/hero_Idle_5.png',
          'hero-Idle/hero_Idle_6.png',
          'hero-Idle/hero_Idle_7.png',
        ],
        run: [ // 移动
          'hero-Run/hero_Run_0.png',
          'hero-Run/hero_Run_1.png',
          'hero-Run/hero_Run_2.png',
          'hero-Run/hero_Run_3.png',
          'hero-Run/hero_Run_4.png',
          'hero-Run/hero_Run_5.png',
          'hero-Run/hero_Run_6.png',
          'hero-Run/hero_Run_7.png',
        ],
        attack: [ // 攻击
          'hero-Attack/hero_Attack_0.png',
          'hero-Attack/hero_Attack_1.png',
          'hero-Attack/hero_Attack_2.png',
          'hero-Attack/hero_Attack_3.png',
          'hero-Attack/hero_Attack_4.png',
          'hero-Attack/hero_Attack_5.png',
          'hero-Attack/hero_Attack_6.png',
          'hero-Attack/hero_Attack_7.png',
        ],
        hurt: [ // 受伤
          'hero-Hurt/hero_Hurt_0.png',
          'hero-Hurt/hero_Hurt_1.png',
          'hero-Hurt/hero_Hurt_2.png',
          'hero-Hurt/hero_Hurt_3.png',
          'hero-Hurt/hero_Hurt_4.png',
          'hero-Hurt/hero_Hurt_5.png',
          'hero-Hurt/hero_Hurt_6.png',
          'hero-Hurt/hero_Hurt_7.png',
        ],
        die: [ // 死亡
          'hero-Die/hero_Die_0.png',
          'hero-Die/hero_Die_1.png',
          'hero-Die/hero_Die_2.png',
          'hero-Die/hero_Die_3.png',
          'hero-Die/hero_Die_4.png',
          'hero-Die/hero_Die_5.png',
          'hero-Die/hero_Die_6.png',
          'hero-Die/hero_Die_7.png',
        ],
      },
      monster: {
        idle: [ // 站立不动
          'monster-Idle/monster_Idle_0.png',
          'monster-Idle/monster_Idle_1.png',
          'monster-Idle/monster_Idle_2.png',
          'monster-Idle/monster_Idle_3.png',
          'monster-Idle/monster_Idle_4.png',
          'monster-Idle/monster_Idle_5.png',
          'monster-Idle/monster_Idle_6.png',
          'monster-Idle/monster_Idle_7.png',
        ],
        run: [ // 移动
          'monster-Run/monster_Run_0.png',
          'monster-Run/monster_Run_1.png',
          'monster-Run/monster_Run_2.png',
          'monster-Run/monster_Run_3.png',
          'monster-Run/monster_Run_4.png',
          'monster-Run/monster_Run_5.png',
          'monster-Run/monster_Run_6.png',
          'monster-Run/monster_Run_7.png',
    
        ],
        attack: [ // 攻击
          'monster-Attack/monster_Attack_0.png',
          'monster-Attack/monster_Attack_1.png',
          'monster-Attack/monster_Attack_2.png',
          'monster-Attack/monster_Attack_3.png',
          'monster-Attack/monster_Attack_4.png',
          'monster-Attack/monster_Attack_5.png',
          'monster-Attack/monster_Attack_6.png',
          'monster-Attack/monster_Attack_7.png',
        ],
        hurt: [ // 攻击
          'monster-Hurt/monster_Hurt_0.png',
          'monster-Hurt/monster_Hurt_1.png',
          'monster-Hurt/monster_Hurt_2.png',
          'monster-Hurt/monster_Hurt_3.png',
          'monster-Hurt/monster_Hurt_4.png',
          'monster-Hurt/monster_Hurt_5.png',
          'monster-Hurt/monster_Hurt_6.png',
          'monster-Hurt/monster_Hurt_7.png',
        ],
        die: [ // 死亡
          'monster-Die/monster_Die_0.png',
          'monster-Die/monster_Die_1.png',
          'monster-Die/monster_Die_2.png',
          'monster-Die/monster_Die_3.png',
          'monster-Die/monster_Die_4.png',
          'monster-Die/monster_Die_5.png',
          'monster-Die/monster_Die_6.png',
          'monster-Die/monster_Die_7.png',
        ],
      }
    }
    

    scene.js中是定义的角色模型

    //scene
    /* by:弦云孤赫——David Yang
    ** github - https://github.com/yangyunhe369
    */
    /**
     * 动画类
     */
    class Animation{
      constructor (type, action, fps) {
        let a = {
          type: type,                                        // 角色类型,hero || monster
          action: action,                                    // 根据传入动作生成不同动画对象数组
          images: [],                                        // 当前引入角色图片对象数组
          img: null,                                         // 当前显示角色图片
          imgIdx: 0,                                         // 当前角色图片序列号
          count: 0,                                          // 计数器,控制动画运行
          fps: fps,                                          // 角色动画运行速度系数,值越小,速度越快
        }
        Object.assign(this, a)
      }
      /**
       * 为角色不同动作创造动画序列
       */
      create () {
        let self = this
        if (self.type === 'hero') {
          for(let item of allImg.hero[self.action]){
            self.images.push(imageFromPath(item))
          }
        } else if (self.type === 'monster') {
          for(let item of allImg.monster[self.action]){
            self.images.push(imageFromPath(item))
          }
        }
      }
    }
    /**
     * 角色模型类
     */
    class Role{
      constructor (_main, obj) {
        let h = {
          _main: _main,                                        // 游戏主函数对象
          type: obj.type,                                      // 角色类型,hero || monster
          x: obj.x,                                            // x 轴坐标
          y: obj.y,                                            // y 轴坐标
          w: obj.w,                                            // 角色图片宽度
          h: obj.h,                                            // 角色图片高度
          speedX: 3,                                           // 角色x轴移动速度
          speedY: 3,                                           // 角色y轴移动速度
          life: 8,                                             // 角色血量
    
          // animation: {  
          //   idle: null,                                        // 站立动画对象
          //   run: null,                                         // 奔跑动画对象
          //   attack: null,                                      // 攻击动画对象
          //   hurt: null,                                        // 受伤动画对象
          //   die: null,                                         // 死亡动画对象
          // },
    
          idle: null,                                          // 站立动画对象
          run: null,                                           // 奔跑动画对象
          attack: null,                                        // 攻击动画对象
          hurt: null,                                          // 受伤动画对象
          die: null,                                           // 死亡动画对象
          canMove: true,                                       // 能否移动
          isFlipX: false,                                      // 是否翻转画布绘制图片,用于绘制人物朝右动画
          isAttacking: false,                                  // 是否处于攻击状态
          isDie: false,                                        // 是否死亡,血量降为 0 即死亡
          direction: null,                                     // 角色朝向
          state: 1,                                            // 保存当前状态值,默认为 0
          state_IDLE: 1,                                       // 站立状态
          state_RUN: 2,                                        // 奔跑状态
          state_ATTACK: 3,                                     // 攻击状态
          state_HURT: 4,                                       // 受伤状态
          state_DIE: 5,                                        // 死亡状态
        }
        Object.assign(this, h)
      }
      /**
       * 初始化方法
       * 对角色的站位方向、状态、不同姿势动画序列进行初始化
       */
      init (info) {
        let self = this
        // 角色初始站位方向,状态
        info.type === 'hero' ? self.direction = 'right' : self.direction = 'left'
        // 是否翻转绘制角色,根据角色朝向判断
        self.isFlipX = self.direction === 'left' ? false : true
        // 角色默认状态值为1,站立状态
        self.state = 1
        // 角色站立
        self.idle = new Animation(self.type, 'idle', 8)
        self.idle.create()
        // 角色奔跑
        self.run = new Animation(self.type, 'run', 4.5),
        self.run.create()
        // 角色攻击
        self.attack = new Animation(self.type, 'attack', 4)
        self.attack.create()
        // 角色受伤
        self.hurt = new Animation(self.type, 'hurt', 4)
        self.hurt.create()
        // 角色死亡
        self.die = new Animation(self.type, 'die', 4)
        self.die.create()
      }
      /**
       * 判断角色状态并返回对应动画对象名称方法
       */
      switchState (state) {
        let self = this
        switch (state) {
          case self.state_IDLE:
            return 'idle'
          case self.state_RUN:
            return 'run'
          case self.state_ATTACK:
            return 'attack'
          case self.state_HURT:
            return 'hurt'
          case self.state_DIE:
            return 'die'
        }
      }
      /**
       * 角色运行动画切换方法
       * game: 游戏对象
       */
      move (game) {
        let self = this,
            stateName = self.switchState(self.state)
        // 累加动画计数器
        self[stateName].count += 1
        // 设置角色动画运行速度
        self[stateName].imgIdx = Math.floor(self[stateName].count / self[stateName].fps)
        // 一整套动画完成后重置动画计数器
        self[stateName].imgIdx === 7 ? self[stateName].count = 0 : self[stateName].count = self[stateName].count
        // 设置当前帧动画对象
        if (game.state !== game.state_STOP) { // 运动时,逐帧显示图片
          if (stateName === 'hurt' && self[stateName].imgIdx === 7) { // 受伤时,执行完一套动画切换为站立状态后允许移动
            // 角色状态改为站立状态
            self.state = self.state_IDLE
            self.canMove = true
          } else if (stateName === 'die' && self[stateName].imgIdx === 7) {
            // 游戏状态改为结束状态
            game.state = game.state_GAMEOVER
            self[stateName].img = self[stateName].images[7]
          } else {
            self[stateName].img = self[stateName].images[self[stateName].imgIdx]
          }
        } else { // 静止时,默认显示第一张图片
          self[stateName].img = self[stateName].images[0]
        }
      }
      /**
       * 执行动画方法
       * game => 游戏引擎对象
       * action => 动作类型
       *  -idle: 站立
       *  -run: 移动
       *  -attack: 攻击
       *  -hurt: 受伤
       */
      animation (game, action) {
        let self = this,
            direction = self.direction,           // 获取角色朝向
            canvas = self._main.game.canvas       // 获取 canvas 对象
        if (game.state === game.state_RUNNING) {
          switch (action) {
            case 'idle':
              self.state = self.state_IDLE
              break
            case 'run':
              self.state = self.state_RUN
    
              // 上下左右键移动事件,并做边界判断
              if (direction === 'up') { // 上
                if (self.y > 25) { // 大于上边界 + 血条高度
                  self.y -= self.speedY
                }
              } else if (direction === 'down') { // 下
                if (self.y < canvas.height - self.h + 15) { // 大于下边界 - 图片高度 + 图片下侧空白部分
                  self.y += self.speedY
                }
              } else if (direction === 'left') { // 左
                if (self.x > -10) { // 大于左边界 - 图片左侧空白部分
                  self.x -= self.speedX
                }
              } else if (direction === 'right') { // 右
                if (self.x < canvas.width - self.w) { // 大于右边界 - 图片宽度 - 图片右侧空白部分
                  self.x += self.speedX
                }
              }
              break
            case 'attack':
              self.state = self.state_ATTACK
              break
            case 'hurt':
              self.state = self.state_HURT
              break
            case 'die':
              self.state = self.state_DIE
              break
          }
        }
      }
    }
    

    main.js中是定义的游戏的主函数,启动方法

    //jsmain.js
    /* by:弦云孤赫——David Yang
    ** github - https://github.com/yangyunhe369
    */
    /**
     * 游戏运行主函数
     */
    let _main = {
      hero: null,                               // hero 实例对象
      hero_info: {                              // hero 初始化参数
        type: 'hero',                           // 角色类型
        x: 40,                                  // x 轴坐标
        y: 350,                                 // y 轴坐标
        w: 100,                                 // 图片宽度
        h: 109,                                 // 图片高度
      },
      monster: null,                            // monster 实例对象
      monster_info: {                           // monster 初始化参数
        type: 'monster',                        // 角色类型  
        x: 900,                                 // monster x 轴坐标
        y: 100,                                 // monster y 轴坐标
        w: 100,                                 // 图片宽度
        h: 113,                                 // 图片高度
      },
      game: null,                               // 游戏引擎对象
      fps: 60,                                  // 游戏运行每秒帧数
      rollPostion: function () {                // 随机角色坐标位置
        let self = this,
            canvas = document.getElementById('canvas'),
            hero = self.hero_info,
            monster = self.monster_info
        // 随机生成 hero 坐标,在左半区域随机
        hero.x = Math.random() * (canvas.width / 2 - hero.w) + 0
        hero.y = Math.random() * (canvas.height - hero.h) + 0
        // 随机生成 monster 坐标,在右半区域随机
        monster.x = Math.random() * (canvas.width / 2 - monster.w) + canvas.width / 2
        monster.y = Math.random() * (canvas.height - monster.h) + 0
      },
      start: function () {                      // 游戏主程序
        let self = this
        // 随机生成 hero,monster 坐标
        self.rollPostion()
    
        // 创建 hero 类
        self.hero = new Role(self, self.hero_info)
        // 创建 hero 动画序列
        self.hero.init(self.hero_info)
    
        // 创建 monster 类
        self.monster = new Role(self, self.monster_info)
        // 创建 monster 动画序列
        self.monster.init(self.monster_info)
    
        // 创建游戏引擎类
        self.game = new Game(self.fps)
        self.game.init(self)
      }
    }
    _main.start()
    

    game.js中定义的是游戏说明以及得分点

    //jsgame.js
    
    /* by:弦云孤赫——David Yang
    ** github - https://github.com/yangyunhe369
    */
    /**
     * 游戏引擎函数
     */
    class Game {
      constructor (fps = 60) {
        let g = {
          actions: {},                                                  // 按键事件方法集,并在按键事件触发时调用对应方法
          keydowns: {},                                                 // 按键事件生成对象集
          state: 1,                                                     // 游戏状态值,初始默认为 1
          state_START: 1,                                               // 游戏初始化
          state_RUNNING: 2,                                             // 游戏开始
          state_STOP: 3,                                                // 游戏暂停
          state_GAMEOVER: 4,                                            // 游戏结束
          canvas: document.getElementById("canvas"),                    // canvas 元素
          context: document.getElementById("canvas").getContext("2d"),  // canvas 画布
          timer: null,                                                  // 轮询定时器
          fps: fps,                                                     // 动画帧数,默认 60
        }
        Object.assign(this, g)
      }
      // 绘制所有游戏素材
      drawAll (hero, monster) {
        let g = this
        // 清除画布
        g.context.clearRect(0, 0, g.canvas.width, g.canvas.height)
        // 绘制背景
        g.drawBg()
        // 绘制角色及角色血条
        g.drawImage(hero)
        g.drawBlood(hero.x, hero.y, hero.life, hero.type)
        g.drawImage(monster)
        g.drawBlood(monster.x, monster.y, monster.life, monster.type)
      }
      // 绘制游戏背景
      drawBg () {
        let img = imageFromPath(allImg.bg)
        this.context.drawImage(img, 0, 0)
      }
      /**
       * 绘制角色血条
       * x:  x轴坐标
       * y:  y轴坐标
       * life:  血量
       * type: 角色类型 => hero || monster
       * height:  血条高度
       * fillColor:  填充颜色
       * borderWidth:  边框宽度
       * borderColor:  边框颜色
       */
      drawBlood (x, y, life, type, fillColor, borderColor, borderWidth = 1, height = 15) {
        let cxt = this.context,
            width = 6 * life // 血量单位宽度 * 总血量
    
        // 根据角色类型不同,绘制不同颜色血条
        if (type === 'hero') {
          fillColor = 'red'
          borderColor = 'red'
        } else {
          fillColor = '#cc3f30'
          borderColor = '#cc3f30'
        }
        // 开始绘制血条
        cxt.beginPath()
        cxt.rect(x + 26, y - 20, width, height)
    
        cxt.lineWidth = borderWidth
        cxt.strokeStyle = borderColor
        cxt.fillStyle = fillColor
    
        cxt.fill()
        cxt.stroke()
      }
      /**
       * 绘制图片
       * obj: 绘制对象
       */
      drawImage (obj) {
        let state = obj.state,                            // 当前角色状态值
            stateName = obj.switchState(obj.state)        // 判断并获取当前动画对象名称
        if (obj.isFlipX) { // 是否水平翻转图像并绘制,true 翻转且角色朝右,false 不翻转且角色朝左
          let x = obj.x + obj.w / 2
          // 把当前状态的一份拷贝压入到一个保存图像状态的栈中
          this.context.save()
          this.context.translate(x, 0)
          this.context.scale(-1, 1)
          this.context.translate(-x, 0)
          this.context.drawImage(obj[stateName].img, obj.x, obj.y)
          // 从栈中弹出存储的图形状态并恢复 CanvasRenderingContext2D 对象的属性、剪切路径和变换矩阵的值
          this.context.restore()
        } else {
          this.context.drawImage(obj[stateName].img, obj.x, obj.y)
        }
      }
      // 游戏结束执行方法
      drawGameOver (hero, monster) {
        let info = ''   // 游戏结束提示信息
        if (hero.isDie) {
          info = '恭喜怪兽获得胜利'
        }
        if (monster.isDie) {
          info = '恭喜英雄获得胜利'
        }
        // 清除定时器
        clearInterval(this.timer)
        // 清除画布
        this.context.clearRect(0, 0, this.canvas.width, this.canvas.height)
        // 绘制背景
        this.drawBg()
        this.context.fillStyle = 'red'
        this.context.font = '48px Microsoft YaHei'
        this.context.fillText(info, 308, 226)
      }
      // 注册事件
      registerAction (key, callback) {
        this.actions[key] = callback
      }
      // 设置逐帧动画
      setTimer (hero, monster) {
        let g = this
        // 事件集合
        let actions = Object.keys(g.actions)
        for (let i = 0; i < actions.length; i++) {
          let key = actions[i]
          if(g.keydowns[key]) {
            // 如果按键被按下,调用注册的action
            g.actions[key]()
          }
        }
        // 判断游戏状态并执行相应事件
        if (g.state === g.state_START){ // 游戏开始
          // 角色移动动画
          hero.move(g)
          monster.move(g)
          // 绘制所有游戏素材
          g.drawAll(hero, monster)
    
          // 绘制准备开始游戏标题
          g.context.fillStyle = 'red'
          g.context.font = '48px Microsoft YaHei'
          g.context.fillText('请按空格键开始游戏', 284, 226)
        } else if (g.state === g.state_RUNNING) { // 游戏运行
          // 角色移动动画
          hero.move(g)
          monster.move(g)
          // 绘制所有游戏素材 
          g.drawAll(hero, monster)
        } else if (g.state === g.state_STOP) { // 游戏暂停
          // 绘制所有游戏素材
          g.drawAll(hero, monster)
    
          // 绘制准备开始游戏标题
          g.context.fillStyle = 'red'
          g.context.font = '48px Microsoft YaHei'
          g.context.fillText('请按空格键开始游戏', 284, 226)
        } else if (g.state === g.state_GAMEOVER) { // 游戏结束
          // 绘制所有游戏素材
          g.drawAll(hero, monster)
          setTimeout(function () {
            // 绘制游戏结束标题
            g.drawGameOver(hero, monster)
          },500)
        }
      }
      /**
       * 注册按键移动事件
       * role: 注册角色对象
       * keyCode: 按键keyCode值
       * direction: 角色移动方向
       * [
       *  {role: hero, keyCode: '87', direction: 'up'},
       *  ...
       * ]
       */
      registerRoleMove (roleList) {
        let game = this
        for (let item of roleList) {
          game.registerAction(item.keyCode, function () {
            if (game.state === game.state_RUNNING && item.role.canMove) {
              // 设置当前角色朝向
              item.role.direction = item.direction
              // 判断是否需要翻转角色动画
              if (item.direction === 'left') {
                // 禁止翻转动画,同时角色朝左移动
                item.role.isFlipX = false
              } else if (item.direction === 'right') {
                // 翻转动画,同时角色朝右移动
                item.role.isFlipX = true
              }
              if (game.keydowns[item.keyCode] === 'down') {
                // 角色不处于受伤状态时才能移动
                if (item.role.state !== item.role.state_HURT) {
                  // 执行奔跑动画
                  item.role.animation(game, 'run')
                }
              } else if (game.keydowns[item.keyCode] === 'up') {
                // 取消奔跑动画
                game.keydowns[item.keyCode] = null
                item.role.animation(game, 'idle')
              }
            }
          })
        }
      }
      /**
       * 注册按键攻击事件
       * roList: [
       *   {
       *     role: 注册角色对象
       *     keyCode: 按键keyCode值
       *   }
       *   ...
       * ]
       */
      registerRoleAttack (roleList) {
        let game = this,                        // 当前游戏引擎类
            hero = roleList[0].role,            // hero 对象
            monster = roleList[1].role          // monster 对象
        for (let item of roleList) {
          let role = item.role.type  // 当前角色类型,hero || monster
          game.registerAction(item.keyCode, function () {
            if (game.state === game.state_RUNNING) {
              if (game.keydowns[item.keyCode] === 'down') {
                // 角色不处于受伤状态时才能攻击
                if (item.role.state !== item.role.state_HURT && item.role.state !== item.role.state_DIE) {  
                  // 执行攻击动画
                  item.role.animation(game, 'attack')
                }
                // 禁止左右移动
                item.role.canMove = false
              } else if (game.keydowns[item.keyCode] === 'up') {
                // 取消攻击动画
                if (item.role.attack.imgIdx === 7) { // 执行一次完整动画后停止
                  // 将按键事件置为空
                  game.keydowns[item.keyCode] = null
                  item.role.animation(game, 'idle')
                  // 检测 hero、monster 是否攻击成功
                  if (role === 'hero') {
                    game.checkAttack(role, hero, monster)
                  } else {
                    game.checkAttack(role, monster, hero)
                  }
                  // 允许左右移动
                  item.role.canMove = true
                }
              }
            }
          })
        }
      }
      /**
       * 检测是否处于攻击范围
       * role1:当前执行攻击动作角色
       * role2:当前被攻击角色
       */
      collideAttack (role1, role2) {
        let r1 = role1,
            r2 = role2
        // 两个角色图片之间的中心点距离小与两站图片宽度之和的一半,即为可攻击
        if (Math.abs((role1.x + role1.w/2) - (role2.x + role2.w/2)) < (role1.w + role2.w - 80)/2 &&
          Math.abs((role1.y + role1.h/2) - (role2.y + role2.h/2)) < (role1.h + role2.h - 150)/2) {
          if (r1.isFlipX && r1.x < r2.x ||
              !r1.isFlipX && r1.x > r2.x) { // r1面向右侧,且r2在r1右侧时;r1面向左侧,且r2在r1左侧时
            return true
          }
        }
        return false
      }
      /**
       * 检测是否攻击成功
       * roleName:角色名称
       * role1:当前执行攻击动作角色
       * role2:当前被攻击角色
       */
      checkAttack (roleName, role1, role2) {
        let game = this
        // 处于角色攻击范围时,即可攻击
        if (game.collideAttack(role1, role2)) {
          if (role2.life === 1) { // 生命值为1时
            // 执行受伤动画
            role2.animation(game, 'die')
            // 禁止移动
            role2.canMove = false
            role2.life -= 1
            // 改变角色死亡状态
            role2.isDie = true
            setTimeout(function () {
              // 生命值为0时,游戏结束
              game.state = game.state_GAMEOVER
            }, 500)
          } else {
            // 执行受伤动画
            role2.animation(game, 'hurt')
            // 禁止移动
            role2.canMove = false
            role2.life -= 1
          }
        }
      }
      /**
       * 初始化函数
       * _main: 游戏入口函数对象
       */
      init (_main) {
        let g = this,
            hero = _main.hero,
            monster = _main.monster
        // 设置键盘按下及松开相关注册函数
        window.addEventListener('keydown', function (event) {
          g.keydowns[event.keyCode] = 'down'
        })
        window.addEventListener('keyup', function (event) {
          g.keydowns[event.keyCode] = 'up'
        })
        g.registerAction = function (key, callback) {
          g.actions[key] = callback
        }
        /**
         * 为 hero 和 monster 注册按键移动事件
         * hero 按键事件,对应 W、S、A、D
         * monster 按键事件,对应 up、down、left、right方向键
         */
        g.registerRoleMove([
          {role: hero, keyCode: '87', direction: 'up'},
          {role: hero, keyCode: '83', direction: 'down'},
          {role: hero, keyCode: '65', direction: 'left'},
          {role: hero, keyCode: '68', direction: 'right'},
          {role: monster, keyCode: '38', direction: 'up'},
          {role: monster, keyCode: '40', direction: 'down'},
          {role: monster, keyCode: '37', direction: 'left'},
          {role: monster, keyCode: '39', direction: 'right'},
        ])
    
        /**
         * 为 hero 和 monster 注册按键攻击事件
         */
        g.registerRoleAttack([
          {role: hero, keyCode: '75'},          // 注册 hero K 键攻击事件
          {role: monster, keyCode: '101'}       // 注册 monster 小键盘 5 键攻击事件
        ])
    
        // 设置轮询定时器
        g.timer = setInterval(function () {
          g.setTimer(hero, monster)
        }, 1000/g.fps)
    
        // 注册游戏全局按键控制事件
        window.addEventListener('keydown', function (event) {
          switch (event.keyCode) {
            // 注册空格键开始游戏事件
            case 32 :
              // 开始游戏
              g.state = g.state_RUNNING
              break
            // P 键暂停游戏事件
            case 80 :
              g.state = g.state_STOP
              break
          }
        })
      }
    }
    

    后记:我没有完全看懂代码啊~

  • 相关阅读:
    系列之前端:从重复造轮子说起
    Asp.Net Core基于JWT认证的数据接口网关Demo
    通过编写一个简单的日志类库来加深了解C#的文件访问控制
    .net core 的图片处理及二维码的生成及解析
    svmtrain和svmpredict简介
    svm小问题
    SVM (support vector machine)
    ubuntu在windows下的wubi安装
    ubuntu在windows下的wubi安装
    [转]无需看到你的脸就能认出你——实现Beyond Frontal Faces: Improving Person Recognition Using Multiple Cues
  • 原文地址:https://www.cnblogs.com/smart-girl/p/11447680.html
Copyright © 2011-2022 走看看