管理复杂的RPG角色数据

对于一个详细的生存角色扮演游戏,需要管理的数据很容易变得压倒性的,如果临时的方式。

首先,你可能想要消除HP,而是有一个伤口系统,各种身体部位可以特别受伤,每个伤害需要个人的关注。 攻击可以是针对性的,伤害的效果取决于它的位置和治疗效果。

下一个显而易见的步骤是管理服装,使每件衣服覆盖特定的身体部位,并为每个部位提供特定的护甲值。 我们还需要跟踪服装冲突,两件衣服试图覆盖同一个区域,所以不能一起穿,除非当它们被devise成穿在其他衣服下面或上面时。

另外,某些身体部位可能会有神奇的效果,或者可能会增加爪子或尖刺。 也许各种各样的肢体可能被replace为半机械人部分或神奇的部分。 更糟糕的是,也许有更多或更less比通常的肢体更多或更less的生物交替的身体计划。

每个肢体可以分成若干部分,例如腿由大腿,膝盖,小腿和脚组成。 我们想单独管理这些部分,但我们也想记住它们代表一条腿。 我们可能需要这样做,以便有针对性的攻击不必被过度具体化,我们可以向玩家提供通知,但不会给出过多的细节。

例如,在“奴隶到Armok”的游戏中,你有时可以得到关于一些特定的脚趾,手指或耳朵的消息。 这在战斗的中间显然是太详细了。 我们不希望被迫提供这样的细节,因为我们没有把这些细节部分加起来成为一个更大的整体。 同时,严格的零件层次结构也是不对的,因为两个arm组成一个角色的“arm”,而每个arm都是“左侧”或“右侧”的一部分,我们希望跟踪这些关系,这样我们就可以向玩家提供适当的信息。

我们也希望所有这些数据被稀疏地存储。 例如,如果你面对的是二十个地精,那么当每个地精完全相同时,单独存储每个地精的每一个肢体和细节是没有意义的。 我们想要在一个地方储存一个典型的妖精,然后每个个体妖精只能通过它与原型的不同来performance。 此外,原型地精可以用它与原型人类的不同来表示。 这不仅仅是为了节省内存,而且也让游戏知道每个角色的特殊性,从而给玩家提供相关信息。 游戏中可能会提到“头部受伤的地精”或“加上手套的地精”,因为这些地精是如何在记忆中performance出来的。

显然,不应该盲目地devise这样的游戏,解决每一个问题。 这种复杂的数据层次需要一个数据库风格的系统来保持所有的细节组织,而一个简单的关系数据库并不能提供一个明显的解决scheme。 像一个实体系统是正确的方法吗?

有没有一种已知的策略来管理这类经验丰富的游戏开发者总是用来制作这类游戏的数据?

这不是一个完整的答案,因为正如其他人在这里指出的那样,这个问题是相当广泛的。 但是我只是想给你一些指点。

body parts / clothing /增强

这是你的系统的核心。 我想你在这里想要的是一个很好的等级消息调度系统,告诉“拥有”的部分,一个子部分是损坏的,例如,如果一个或多个手指坏了,你就不能举起锤子。 这也允许从手指通过arm通过arm派送到主体。 主体可以派遣更大的游戏管理员说:“看,这个人不能攻击(因为他有一个手指坏了)”。 你也可以通过停用更大的部分来closures子部分的任何动作,所以如果演员的arm在吊索中,他们可能不会使用任何手指。 我强烈建议你实现控制的层次结构

服装排斥系统实际上只是把身体分解到所有区域,例如arm,腿部,而且还包括边界区域,例如袖口,腰部,衣领,并且确保任何尝试穿上新装备的衣服排除系统都不是相互矛盾的。 Bitflags / bitfields / bitmasks将是一个快速的方法来检查什么是可穿戴的,在一个(?)操作。

将左右arm分为“arm”,这只是一个层面而已。

We'd also want all this data to be stored sparsely.

那么你可以做的最好的是每个都有一个实例,并使用指针,这取决于平台往往是32位或64位(4-8字节)。 实际上,你可以做得稍微好点:你可以设置一个8位或者16位的键控数组(256或者16384个元素),然后用一个unsigned byte或者一个unsigned short键入。 这样可以减less索引大小,从而可以为每个CPU字存储更多的索引。 你可能也希望所有的原件在内存中是连续的。

另请参阅作为原型的单体对象的组合(更多关于下面的组合)。

For example, if you're facing twenty goblins, there's no point in individually storing every limb and detail for each goblin when they are all identical. We want to store a prototypical goblin in one place

所以,撰写你的原型,并把它们放在一边。 查看更多下面。

Further, the prototype goblin could be represented by how it differs from the prototype human.

即使超类/子类似乎是正确的关系, 要这样做,因为你以后会把自己锁在角落里。 而是编写原型对象并进行区分:为每个身体部分分配一个数字(或string)ID,然后对整个身体的部分集合进行散列。 这个散列允许你比较演员物种; 如果散列/物种不同,那么你可以用数字比较个体身体部位,这是非常快速的,尤其是对于vector化的代码。

实际上,你可以为你研究JavaScript的原型inheritance系统提供很多信息。 这是一个几乎完美的契合。 只要你理解了这个概念,在另一种语言中实现类似就相当简单了。

Obviously one shouldn't jump blindly into designing such a game

不,但是,除非您已经广泛地testing了多个选项,否则您将难以准确知道最有效的方法。 这就是为什么你应该遵循别人的建议和原型。 在这里任何人都不可能给你一个最合适的建筑方法,因为这将取决于你的devise的所有不同方面如何结合在一起 – 这只能通过大量的实验来获得。 开始简单,不要担心效率。


(明确)“控制权”

一个如此普遍的模式,我不确定它是真正的命名。 它确保控制stream量保持健康/避免意大利面。 你有一系列的控制类,比如说,游戏,身体,arm,手,手指(越来越细化)。 游戏具有调用人体function的function; 同样的身体和arm等。 下线; 它可能不是update ,但其他命名的function,例如Arm可能会调用Hand.wield 。 尊重等级是因为你试图让直接的父母(或者至less是祖先)和孩子说话,孩子回到直接的父母身边(有时使用松散耦合,所以没有父母的直接引用)。 你可以让孩子跟祖父母说话,反之亦然,但是由于你跳过了树的层次,这使得控制stream很难跟随。 你也要确保整个系统的通信从树的顶端出来,在这个例子中是Body; 没有手把信息发送给超级系统。

基本上,Body是外部世界的接口,通过这个接口你可以传送所有外出的信息,因此很容易严格地关注演员正在发生的事情。 但是,最终,在哪里以及是否跳过关卡都取决于开发人员的判断,因为如果您始终严格使用此方法,则会导致更高级别的函数定义的镜像。