原质询:

你好,

我正在创建非常简单的爱好项目-基于浏览器的多人游戏.我一直在设计表格来存储关于任务/技能要求的信息.

目前,我用以下方式设计了我的桌子:

  • user(用户基本信息)
  • stat(各种统计数据)
  • user_stats(将每个用户与统计数据联系起来)

另一个示例:

  • monsters(NPC敌人基本情况)
  • monster_stats(使用上面相同的统计数据表,将怪物与统计数据连接起来)

这些都是简单的 case .我必须承认,我在为不同的事情设计需求时遇到了困难,例如任务.示例任务A可能只有最低的字符级别要求(这很容易实现),但另一个任务B有许多其他要求(完成任务、获得技能、拥有特定物品等)——设计存储此类信息的表格的好方法是什么?

以类似的方式-存储有关技能要求的信息的有效方式是什么?(特定字符类、最低级别等).

我将非常感谢任何有关创建数据库驱动的游戏的帮助或信息.

编辑:

谢谢你的回答,但我希望得到更多.由于我在为可手工制作的物品设计一个相当复杂的数据库布局时遇到了一些问题,所以我开始为这个问题提供最大的帮助.

我希望收到与设计用于存储游戏数据的数据库的最佳实践相关的文章/代码片段/任何东西的链接(这类信息的一个很好的例子可以在buildingbrowsergames.com上找到).

如果有任何帮助,我将不胜感激.

推荐答案

我将对此进行编辑,以添加尽可能多的其他相关问题,尽管我希望OP能解决我上面的 comments .作为一名专业的网络游戏开发人员,我说了几年的话,作为一名业余的网络游戏开发人员,我也做了很多年,不管它有多大的价值.

在线游戏隐含着某种持久性,这意味着您大致拥有两种类型的数据-一种是您自己设计的,另一种是玩家在游戏过程中创建的.最有可能的是将两者都存储在数据库中.确保您对这些内容有不同的表,并通过通常的数据库规范化规则正确地交叉引用它们.(例如,如果你的玩家制作了一把大刀,你不会用剑的所有属性创建一个完整的新行.使用每实例属性在Player_Items表中创建一个新行,并引用保存每项类型属性的Item_Types表中的Backword行.)如果您发现一行数据包含您设计的某些内容以及玩家在游戏过程中更改的某些内容,则需要将其标准化为两个表.

这确实是典型的类/实例分离问题,适用于此类游戏中的许多事情:地精实例不需要存储作为地精意味着什么的所有细节(例如绿色皮肤),只需要存储与该实例相关的内容(例如位置、当前健康状况).有些时候,构造行为有一个微妙之处,即需要基于类数据创建数据.(例如,根据地精类型的最大运行状况设置地精实例的起始运行状况.)我的建议是将这些硬编码到创建实例并为其插入行的代码中.这种信息很少改变,因为在实践中几乎没有这种价值观.(生命、耐力、法力等可消耗资源的初始分数……仅此而已.)

try 找到一个一致的术语来区分实例数据和类型数据-这将使您稍后在修补实时游戏时更容易操作,并且不会因为编辑错误的表格而使玩家的辛勤工作付诸东流.这也使得缓存变得容易得多-您通常可以不受惩罚地缓存您的类/类型数据,因为只有当您(设计者)将新数据推到那里时,它才会发生变化.您可以运行它通过memcached,或考虑加载它在启动时,如果您的游戏有一个连续的进程(即.不是PHP/ASP/CGI/等)等.

请记住,一旦上线,从设计端数据中删除任何内容都是有风险的,因为玩家生成的数据可能会重新引用它.在部署到活动服务器之前,请在本地彻底测试所有内容,因为一旦部署到活动服务器上,就很难将其删除.考虑能够以安全的方式将这些数据行标记为已删除的方法-可能是布尔型"live"列,如果设置为false,则意味着它将不会出现在典型查询中.想一想,如果禁用玩家赚来的物品,会对玩家产生什么影响(如果这些物品是他们付钱买的,那就加倍了).

在不知道如何设计游戏的情况下,无法真正回答实际制作方面的问题.数据库设计必须遵循游戏设计.不过,我会把一个琐碎的 idea 说一遍.也许你会想要创建一个基本的物体,然后用符文或水晶或其他任何东西来增强它.为此,您只需要在Item实例和增强实例之间建立一对多关系.(请记住,您可能也有项目类型表和扩充类型表.)每个扩充可以指定项目的属性(例如,耐久性、战斗中造成的最大伤害、重量)和修饰符(通常作为乘数,例如.1.1增加10%的 prize ).你可以看到我关于如何实现这些修改效果herehere的解释-适用于临时技能和法术效果的原则与适用于永久物品修改的原则相同.

对于数据库驱动的游戏中的角色统计,我通常会建议坚持使用一列(整数或浮点)统计的天真方法.稍后添加列并不是一个困难的操作,因为您将大量读取这些值,所以您可能不想一直对它们执行联接.然而,如果你真的需要灵活性,那么你的方法是好的.这与我在下面建议的技能水平表非常相似:许多游戏数据可以用这种方式建模——将一个事物的类或实例映射到另一个事物的类或实例,通常使用一些额外的数据来描述映射(在本例中,统计值).

一旦设置了这些基本联接-实际上还有任何其他复杂的查询,这些查询是由类/实例数据以一种可能对您的代码不方便的方式分离而产生的-考虑创建一个视图或存储过程来在幕后执行它们,这样您的应用程序代码就不必再担心它了.

当然,其他好的数据库实践也适用--当您需要确保多个操作自动发生时使用事务(例如,交易),将指数放在您最常搜索的字段上,在静默期使用吸尘器/优化表/任何工具来保持性能,等等.

(以下是原始答案.)

老实说,我不会将任务需求信息存储在关系数据库中,而是存储在某种脚本中.最终,你对"需求"的理解呈现出几种不同的形式,这些形式可以利用不同类型的数据(例如等级、等级、之前完成的任务、物品拥有情况)和操作员(一个等级可能是最低或最高,一些任务可能需要一件物品,而另一些任务可能需要它的缺席,等等),更不用说连接和分离(一些任务要求满足所有要求,而其他任务可能只要求满足其中一个要求).用命令式语言更容易指定这类事情.这并不是说数据库中没有quest表,而是说您没有try 将有时是任意的需求编码到模式中.我需要一个requirement_script_id列来引用外部脚本.我想如果合适的话,也可以将实际脚本作为文本字段放入数据库中.

不过,技能要求适用于DB,并且在您通过特定课程的各个级别时学习技能的典型游戏系统中,这些要求相当微不足道:

table skill_levels
{
    int skill_id FOREIGN KEY;
    int class_id FOREIGN KEY;
    int min_level;
}

myPotentialSkillList = SELECT * FROM skill_levels INNER JOIN
    skill ON skill_levels.skill_id = skill.id
    WHERE class_id = my_skill
    ORDER BY skill_levels.min_level ASC;

需要技能树吗?添加一列prerequisite_skill_id.等等

Database相关问答推荐

如何从大型Oracle数据库中删除列?

无法连接MatrixOne(来自GitHub)

我们可以出于不同目的在同一 postgres 数据库上同时进行物理和逻辑复制吗?

文件存储的推荐位置 - 在数据库或其他什么地方?

Android SQLiteno such table异常

分布式数据库管理系统 (DDBMS) 中的水平与垂直碎片

Java中基于文件的数据库

主必须包括表的分区位置错误中的所有列?

MongoDB:查询具有两个相等字段 $match 和 $eq 的文档

在 Oracle 的 Check 语句中使用子查询

Laravel 5 从 URL 获取 ID

在插入数据库之前而不是在输出时转义 HTML 是不是一个坏主意?

SQLite 中内存数据库的优势

使用varchar作为主键?

在 PostgreSQL 中使用 pg_notify(text, text) 监听/通知

为什么在连接表上有一个主键不好?

哪个更重要?数据库设计或编码?

C++ SQL 数据库库比较

QSqlDatabase & QSqlQuery 的正确方法是什么?

DBMS中数据模型和数据库模式的区别?