DMV2开发记录(二)世界boss

背景

想做一个可以全部人一起打boss的玩法 但是又局限在了这样的回合制 于是打算这样子实现

  1. 建立websocket链接 将当前玩家伤害数据上报
  2. 将伤害信息分发给所有在攻略boss的玩家
  3. 将伤害实时弹出显示

参考文章

使用技术

具体实现

定义消息结构

根据上述需求 分析得到 我们需要发送伤害信息给所有人 仅此一个简单消息 因此我们设计如下

javascript 复制代码
// 系统消息
const msg1 = {type: 'system', subType: 'connect-success', bossInfo: "boss相关信息"}
// 伤害信息
const msg2 = {type: 'battle', subType: 'hurt', bossInfo: "boss相关信息", userInfo: "当前用户信息"}
// 心跳包
const msg3 = {type: "system", subType: "heart-beat"}

使用type区分业务大类 subType细分业务 后续拓展可以增加subType即可 针对新类型也可以做默认处理(之前开发即时聊天有了解过一些)

定义boss数据

boss数据可以用副本的形式实现 将所有boss汇总到一个副本里面 使用bossid做区分 额外增加单日讨伐次数 以及 最大回合数限制

javascript 复制代码
[`Z_BOSS_WAR--${ALL_DM_PREFIX.BOSS_WAR(2)}`]: {
    rememberProgress: true,
    missionId: 1,
    mapId: commonMapId,
    backgroundImage: `${DIGIWORLD_PATH}/fileIsland/龙眼湖.jpg`,
    bgImg: `${FULL_RES_PATH}/bossWar/bg-default.png`,
    maxTimes: 3, // 单日最大次数
    maxRound: 10, // 最大回合数
    unlockLimit: {
      userLevel: 10,
      completeMission: null
    },
    recommend: {},
    name: '高贵南瓜兽',
    description: '',
    // 敌人列表
    enemyList: [
      {
        lineName: 'Z_BOSS_WAR', //路线
        id: ALL_DM_PREFIX.BOSS_WAR(2), // 当前dm id
        level: 30,
        presetAttr: {
          ...$A.L1(30),
          de: 200,
          spd: 200
        }
      }
    ],
    // 掉落物
    spoilsList: [
      {
        id: 'OTHER_1',
        getItem: getItem(100, [100, 200])
      }
    ]
  }

切入点

在原有的战斗逻辑基础上 额外增加一个对战类型 (之前预留的) 判断是这个类型就初始化socket即可

javascript 复制代码
computed: {
    isBossMatch () {
      return this.battleType === "boss"
    }
},
mounted () {
    if (this.isBossMatch) {
        // 初始化socket
        this.initSocket()
    }
}

消息处理

  1. 系统消息 目前系统消息只有连接成功心跳 所以只需处理伤害逻辑
  2. 伤害逻辑需要判断是不是我自己造成的伤害 需要排除
  3. 将收到的伤害信息 实时修改内存中的boss血量数据 并显示到界面上
javascript 复制代码
let idx = this.tamersDamageList.push({ ...damage })

this.$nextTick(() => {
    anime({
        targets: this.$refs.damageBox[idx - 1],
        translateY: [{ value: `-${getRandomNum(20,40)}px` }],
        translateX: [{ value: `${getRandomNum(-20,40)}px` }],
        opacity: [{ value: 1 }, { value: 0, delay: 1000 }],
        duration: 1000
    })
})

将伤害显示到界面上 通过随机一个x y偏移值 达到伤害跳出的效果

伤害统计

这个就是交给后台去实现了 貌似是存到了redis里面 咱也不懂

讨伐结束

boss的血量比较多 然后伤害却很低 为了限制给单个玩家刷数据 额外设定了对战回合数上限 10回合之后boss就会逃跑了

其他

开发完之后 感觉背景挺单调的 突然想到了之前的lottle下面简单贴出用法 用来实现背景的动画

javascript 复制代码
<template>
  <div style="lottie-box">
    <div id="domId" style="width: 100vw;height: 100vh">
    </div>
  </div>
</template>

<script>
import Lottie from 'lottie-web'
const JSON_DATA = require("@/static/other/lottie/wsj.json")

export default {
  mounted() {
    this.init()
  },
  methods: {
    init() {
      const animation = Lottie.loadAnimation({
        container: document.getElementById('domId'), // 绑定dom节点
        renderer: 'canvas', // 渲染方式:svg、canvas
        loop: true, // 是否循环播放,默认:false
        autoplay: true, // 是否自动播放, 默认true
        animationData: JSON_DATA,// AE动画使用bodymovie导出为json数据
        rendererSettings: {
          preserveAspectRatio: 'none', // 不保留长宽比
          progressiveLoad: false, // 禁用渐进加载
          hideOnTransparent: true // 在透明背景时隐藏动画
        }
      })

      animation.addEventListener('DOMLoaded', function() {
        console.log(`帧数:${animation.totalFrames}`);
      });

      // animation.playSegments([[0,5]], true)

      // animation.play(); // 播放,从当前帧开始播放

      // animation.stop(); // 停止,并回到第0帧

      // animation.pause(); // 暂停,并保持当前帧

      // animation.goToAndStop(value, isFrame); // 跳到某个时刻/帧并停止isFrame(默认false)指示value表示帧还是时间(毫秒)

      // animation.goToAndPlay(value, isFrame); // 跳到某个时刻/帧并进行播放

      // animation.goToAndStop(30, true); // 跳转到第30帧并停止

      // animation.goToAndPlay(300); // 跳转到第300毫秒并播放
      
      // animation.goToAndPlay(0); // 从头播放动画

      // animation.playSegments(arr, forceFlag); // arr可以包含两个数字或者两个数字组成的数组,forceFlag表示是否立即强制播放该片段

      // animation.playSegments([10,20], false); // 播放完之前的片段,播放10-20帧

      // animation.playSegments([[0,5],[10,18]], true); // 直接播放0-5帧和10-18帧

      // animation.setSpeed(speed); // 设置播放速度,speed为1表示正常速度

      // animation.setDirection(direction); // 设置播放方向,1表示正向播放,-1表示反向播放

      // animation.destroy(); // 删除该动画,移除相应的元素标签等。

    }
  }
}
</script>
<style lang="less">
.lottie-box {
  overflow: hidden;
  width: 100%;
  height: 100%;
}
</style>

遇到的一些问题

  1. 由于伤害是经过了防御值计算后发送给所有用户的 因此 来自其他玩家的伤害数据不需要参与防御值的计算 又得单独处理
  2. boss的初始化问题 目前还是先比较蠢手动创建本地数据 再通过接口创建
  3. 奖励问题 目前还处于测试阶段 因此就没什么奖励了 后续打算做boss券去换道具

结束

感谢阅读 你又摸鱼了10分钟

相关推荐
前端大白话7 分钟前
救命!这10个Vue3技巧藏太深了!性能翻倍+摸鱼神器全揭秘
前端·javascript·vue.js
嘻嘻嘻嘻嘻嘻ys9 分钟前
《Vue 3全栈架构实战:Vite工程化、Pinia状态管理与Nuxt 3深度解析》
前端·后端
前端大白话10 分钟前
前端人必看!10个JavaScript“救命”技巧,让你告别加班改Bug
前端·javascript·程序员
cg501720 分钟前
Vue回调函数中的this
前端·javascript·vue.js
前端太佬22 分钟前
从零到一实现扫码登录:一个前端菜鸟的踩坑实录
前端·javascript·架构
yuanmenglxb200433 分钟前
微信小程序核心技术栈
前端·javascript·vue.js·笔记·微信小程序·小程序
爱编程的鱼34 分钟前
如何让 HTML 文件嵌入另一个 HTML 文件:详解与实践
前端·html
_092738 分钟前
Vue 2 与 Vue 3 的核心区别及 Vue 3 新特性详解
前端
David凉宸39 分钟前
一文带你使用Vue完成移动端(apk)项目
前端
会飞的鱼先生1 小时前
Vue3的内置组件 -实现过渡动画 TransitionGroup
前端·javascript·vue.js·vue