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

相关推荐
wearegogog1232 小时前
基于 MATLAB 的卡尔曼滤波器实现,用于消除噪声并估算信号
前端·算法·matlab
Drawing stars2 小时前
JAVA后端 前端 大模型应用 学习路线
java·前端·学习
品克缤2 小时前
Element UI MessageBox 增加第三个按钮(DOM Hack 方案)
前端·javascript·vue.js
小二·3 小时前
Python Web 开发进阶实战:性能压测与调优 —— Locust + Prometheus + Grafana 构建高并发可观测系统
前端·python·prometheus
小沐°3 小时前
vue-设置不同环境的打包和运行
前端·javascript·vue.js
qq_419854053 小时前
CSS动效
前端·javascript·css
烛阴3 小时前
3D字体TextGeometry
前端·webgl·three.js
桜吹雪4 小时前
markstream-vue实战踩坑笔记
前端
C_心欲无痕4 小时前
nginx - 实现域名跳转的几种方式
运维·前端·nginx
花哥码天下4 小时前
恢复网站console.log的脚本
前端·javascript·vue.js