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

相关推荐
zengyuhan50316 分钟前
Windows BLE 开发指南(Rust windows-rs)
前端·rust
醉方休19 分钟前
Webpack loader 的执行机制
前端·webpack·rust
前端老宋Running28 分钟前
一次从“卡顿地狱”到“丝般顺滑”的 React 搜索优化实战
前端·react.js·掘金日报
隔壁的大叔28 分钟前
如何自己构建一个Markdown增量渲染器
前端·javascript
用户44455436542630 分钟前
Android的自定义View
前端
WILLF31 分钟前
HTML iframe 标签
前端·javascript
枫,为落叶1 小时前
Axios使用教程(一)
前端
小章鱼学前端1 小时前
2025 年最新 Fabric.js 实战:一个完整可上线的图片选区标注组件(含全部源码).
前端·vue.js
ohyeah1 小时前
JavaScript 词法作用域、作用域链与闭包:从代码看机制
前端·javascript
流星稍逝1 小时前
手搓一个简简单单进度条
前端