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分钟

相关推荐
yuhaiqiang10 分钟前
为什么这道初中数学题击溃了所有 AI
前端·后端·面试
djk888813 分钟前
支持手机屏幕的layui后台html模板
前端·html·layui
紫_龙15 分钟前
最新版vue3+TypeScript开发入门到实战教程之watch详解
前端·javascript·typescript
默默学前端1 小时前
ES6模板语法与字符串处理详解
前端·ecmascript·es6
lxh01131 小时前
记忆函数 II 题解
前端·javascript
我不吃饼干1 小时前
TypeScript 类型体操练习笔记(三)
前端·typescript
华仔啊1 小时前
除了防抖和节流,还有哪些 JS 性能优化手段?
前端·javascript·vue.js
CHU7290351 小时前
随时随地学新知——线上网课教学小程序前端功能详解
前端·小程序
清粥油条可乐炸鸡1 小时前
motion入门教程
前端·css·react.js
这是个栗子1 小时前
【Vue3项目】电商前台项目(四)
前端·vue.js·pinia·表单校验·面包屑导航