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

相关推荐
蓝倾16 分钟前
淘宝批量获取商品SKU实战案例
前端·后端·api
comelong21 分钟前
Docker容器启动postgres端口映射失败问题
前端
花海如潮淹23 分钟前
硬件产品研发管理工具实战指南
前端·python
用户38022585982423 分钟前
vue3源码解析:依赖收集
前端·vue.js
WaiterL24 分钟前
一文读懂 MCP 与 Agent
前端·人工智能·cursor
gzzeason26 分钟前
使用Vite创建React初始化项目
前端·javascript·react.js
又双叒叕77827 分钟前
React19 新增Hooks:useOptimistic
前端·javascript·react.js
归于尽1 小时前
V8 引擎是如何给 JS"打扫房间"的 ?
前端·javascript
小old弟1 小时前
让对象保持定义的顺序来排列
前端
漫天星梦1 小时前
前端列表页大数据内存优化的思考
前端·面试