论可复用的游戏服务器端开发框架(四)

战斗系统的模型构建思考

战斗系统是一个游戏的玩法核心,也是游戏之间差别最大的地方,想要建立可复用的模型,可谓困难最大。但是,游戏的玩法本身也是有分类和传承的。需要特别注意的是,作为服务器端程序,战斗系统的职责是有多种不同层级的:

  1. 记录战斗结果,发放战斗奖励。很多开房间和按“局”算的游戏,如棋牌类,其游戏本身是分为很多“局”的。游戏是在一局结束后,才结算所有的奖励。另外如《地下城与勇士》(DNF),其游戏为一个个地下城“副本”,本身也是这种分局的。如果服务器端只是为了游戏完成一局后做“结算”,那么其逻辑还是比较简单的:主要就是校验游戏中的消耗与产出是否合理,有无作弊嫌疑,然后更具战斗数据,发放战斗奖励给玩家。这种模型下其实无需很复杂的模型,无论任何的玩法,实际上都可以用一个“校验与奖励”函数作为抽象即可。如果战斗过程中有消耗品使用或者奖励掉落,还要增加一个消耗品函数和奖励掉落函数即可。
  2. 在二维游戏场景下,对战斗过程进行模拟,且时常会结合帧同步广播来协调游戏。例子就如著名的《英雄联盟》。这一类战斗服务器,往往会作为“主广播器”,生成AI的行为,转发广播玩家的动作,同时计算每个战斗动作的“成败输赢”。这种做法其实和一个客户端计算战斗过程是差别不大的。这种战斗服务器的抽象模型是由几个部分组成:AI控制+状态广播+战斗判定。每一个战斗“帧”,服务器都会更新所有玩家、怪物的状态,然后判定战斗结果,最后广播状态和战斗情况给客户端。这种模型是相对比较复杂的,其最复杂的地方在于处理AI和判定战斗结果的时候,必须在内存中根据二维的战场状况,重现整个游戏情况。这对于一般来说不显示画面的服务器端程序来说,是比较复杂的。
  3. 在三维游戏场景下,对战斗过程的模拟和广播协调。很多FPS游戏都是这种,而著名的WOW也是这一类例子。其实这个模型和上面第2种情况是类似的,只不过3维空间的计算复杂程度比二维更高。

基于上面所说,一个战斗系统确实是游戏中最复杂的部分,因此我们的建模也不能很轻易简单的完成,而是应该分为几个不同的层次和阶段。第一个层次对应最简单的战斗结果校验和奖励模型:

在这里,我们使用“战斗关卡”这个模型来抽象战斗内容,“奖励对象”只是一个用于抽象可能存在的不同奖励内容的接口。一般来说我们的奖励是物品道具、货币,但是也有可能会有更复杂的内容,比如开通某种特殊权限,完成某个任务等等。这些复杂的“战斗奖励”也许不是一个RPG的物品基类能涵盖的。所以不如以组合的形式来耦合关卡奖励和具体的物品。由于战斗关卡的数据项目一般很少,所以就不列举数据属性的设计,而专门关注关键行为的模型:

  • 战斗关卡
    • 根据ID从持久化数据中构建关卡
    • 返回战斗关卡的介绍,应该返回一个游戏自定义的介绍数据结构。
    • 输入所有进入玩家对象,开始一局关卡游戏。有可能开始一局游戏会扣减某些玩家资源和检查是否能开始游戏。
    • 输入玩家对象,计算关卡中掉落物品
    • 输入玩家对象,计算关卡中消耗物品
    • 判断关卡是否结束。根据战斗关卡的数据来判断是否应该结束关卡。
    • 输入所有当前玩家对象,进行关卡结束的计算,返回关卡的奖励。此操作会计算游戏过程中的掉落物品和消耗物品。
  • 关卡奖励
    • 输入玩家对象,执行奖励(虚函数)

在第二个层次中,战斗系统的模型会变的复杂很多,其中有一块是关于AI模块的。关于AI的模型本文恐怕无法简单完成,因此可以把他看成是一个黑盒子。当然AI简单的用一个状态机实现也可以。在这种情况下,战斗的标准流程是:按帧接受玩家操作,AI产生怪物/NPC操作,计算战斗结果,更新战场状态,广播战场状况。因此模型大致如下:

在这个模型下,战斗主要执行逻辑对象,是由“帧同步广播器”来执行的,当然也有可能游戏不是帧同步模型的,但是无论如何都会有一个战斗驱动器来循环的调度战斗进行。如果这个战斗驱动器是帧同步或定时器的,那么游戏就会是实时游戏,如果这个战斗驱动器是由玩家命令触发(可能带超时触发)的,那么游戏可能会是回合制的。不过归根结底,战斗系统都是一个“战斗判定”循环,只是这个循环的定时器的快慢差别,以及是否能由玩家主动暂停或加速的差别。因此以上对象的主要行为应该包括:

  • 战斗驱动器(此处是“帧同步广播器)
    • 驱动帧(虚函数)函数:此函数可以由各种不同的情况触发,如定时器、玩家命令等。负责执行具体的战斗计算状况。
  • 战场状态集。有时候关卡的战斗状态和这个对象是同一个对象。
    • 获得战场状态:包括所有战场上角色对象及其2D、3D坐标
    • 输入目标角色与技能范围,返回是否命中。(辅助函数,根据2D/3D的差别,会有很多不同的模型,如射线命中判断用于FPS)
  • AI模块。AI模块可能包含复杂的状态机模型,但只有一个驱动函数而已。
    • 输入游戏角色对象,执行其AI结果操作。(虚函数)

关于战斗驱动器的几种模型下表有一个分类:

关于战斗动作,在2维和3维下略有不同(同理,如果有1维的游戏也是一样的),但是仅仅是参数的区别。实际上,针对特定类型的游戏玩法,比如FPS或者MOBA&RTS类型,这里的战斗动作都具备相当高的可复用可能。这些动作的内容各有不同,但是其“动作”的主要行为是:

  • 判断——是否碰撞(命中),返回碰撞对象
  • 动作——修改发出动作对象以及碰撞对象状态

对于纯数值类型游戏,其实就相当于0维空间游戏,战斗动作的判断实际上返回的对象由动作本身确定,无需空间计算。这在很多RPG或者策略类游戏中是很常见的。

最后总结一下战斗系统的完整流程,在有些游戏中,关卡和战斗是配合一起操作的,但是有些游戏则没有关卡,只有战斗,不过这种游戏主要是世界地图的MMORPG,现在这类游戏已经渐渐式微了:

尽管战斗系统是如此的复杂和多变,但是其运作还是一个模拟状态变化的系统,所以还是有不同层次的可重用模型可以设计。核心的战斗驱动就是模拟时间因数,而战斗动作则负责对空间因数进行模拟。关卡系统是对战斗的一个时空区隔,也是各种奖励、消耗的小结,因此更常见于游戏当中。

明天接着讲:

副本系统的构建思考

感谢大家的阅读,如觉得此文对你有那么一丁点的作用,麻烦动动手指转发或分享至朋友圈。如有不同意见,欢迎后台留言探讨。

原文发布于微信公众号 - 韩大(handa1740168)

原文发表时间:2016-01-12

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏哲学驱动设计

UML 图使用心得

在软件开发中,从需求工程到代码工程,都离不开 UML 图的绘制。今天简要总结一下我以往使用 UML 图的一些体会。 很多图,都是由原始需求到代码的一种转换,只是...

1916
来自专栏峰会SaaS大佬云集

更新c++学习笔记 第一章

参加了几次笔试,发现有很多c++方面的问题被卡了。从现在开始进攻c++。之后会陆续更新c++学习笔记。

311
来自专栏张善友的专栏

浅述RDF,畅想一下FOAF应用

最近一直都在看一些RDF和Semantic Web方面的东西,本来有一个同事是来自Tsinghua AI实验室的,本想跟他好好讨论讨论,不过估计也没有机会了。国...

20110
来自专栏程序员互动联盟

小菜学Chromium开发系列:OpenGL学习

风雨送春归,飞雪迎春到。已是悬崖百丈冰,犹有花枝俏。俏也不争春, 只把春来报。待到山花烂漫时,她在丛中笑。 这首《毛泽东诗词》·卜算子·咏...

2795
来自专栏性能与架构

Redis新增位置查询功能 - Redis Geo

移动互联网中基于位置信息的服务(Location Based Service,LBS)越来越重要。但是,目前位置信息的使用过程中存在诸多挑战如相邻计算不准确等。...

3707
来自专栏大数据文摘

Twitter新政:变革140字推文限定背后,Twitter有何新目标?

1596
来自专栏方盼的专栏

基于知识图谱算法的网络故障智能诊断探索

17年这波AI浪潮推动着各行各业在进行着智能化和AI+的尝试,而当前业界在网络故障智能监控诊断这块到目前为止还没有可参照的成熟案例。知识图谱相对于很火的深度学习...

5833
来自专栏数据派THU

独家 | 提速20倍!3个细节优化Tableau工作簿加载过程(附实例)

Katarzyna "Kasia" Gasiewska的Tableau Public主页上经常有一些精彩的可视化作品,她拥有100多位粉丝,如果你没有位列其中,...

1612
来自专栏大数据挖掘DT机器学习

【实战帖】使用Python分析社交网络数据

目录 数据抓取 一、直接抓取数据 二、模拟浏览器抓取数据 三、基于API接口抓取数据 数据预处理 可视化 数据分析 扩散深度 扩散速度 空间分布 节点属性 网...

8229
来自专栏hotqin888的专栏

浅谈onlyoffice文档协作在工程设计中的应用——共享excel计算书

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/hotqin888/article/det...

1662

扫码关注云+社区