使用PHP和MySQL设计良好的体验和关卡系统

时间:2014-06-11 16:46:54

标签: php mysql

我正在使用PHP& amp;来实现一个游戏化平台MySQL的。人们可以通过几个动作获得经验值(测验,完成其个人资料,转到一个页面......)

我有一个名为members的表,我存储了用户的个人资料。包括level_id

CREATE TABLE members (
    `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
    `username` varchar(250) NOT NULL,
    `level_id` int(10) unsigned NOT NULL DEFAULT '1',
    PRIMARY KEY (`id`),
    UNIQUE KEY `username` (`username`),
    KEY `level_id` (`level_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

我有一个名为points的表,每次用户获得经验值(XP)时都会有一个注册表。

CREATE TABLE points (
  `id_member` int(10) unsigned NOT NULL,
  `date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `points` int(11) NOT NULL,
  KEY `id_member` (`id_member`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

我有另一张名为levels的桌子,在那里我录制了关卡系统:

CREATE TABLE levels (
    `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
    `name` varchar(250) NOT NULL,
    `experience_needed` int(10) unsigned NOT NULL,
    PRIMARY KEY (`id`),
    UNIQUE KEY `name` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

每次将记录插入points表时,我都会计算新的用户级别,在experience_needed表中查找正确的levels

然后我使用members字段将用户级别保持在level_id表中。

现在我问这是否是最好的方法。其他替代方案是:

  • 每次选择用户信息时计算level_id的视图
  • 而不是保持用户的水平,我可以在每次需要时计算
你怎么看? 提前致谢

1 个答案:

答案 0 :(得分:1)

你是对的level_id并非绝对必要,完全规范化的架构不会包含它。

您基本上是在缓存level_id以使阅读更容易,这可能会有所不同,具体取决于您的应用程序。如果读取/显示用户的级别的次数比授予的次数要多得多,并且每个成员可以有很多points个记录,那么阅读的性能和简单性可能是值得的。成本是每个用户行的少量存储,对points的写入影响很小,以及使level_idpoints中的数据保持同步的复杂性增加。

最后一个是非规范化的主要缺点:它违反了Single Source of Truth规则,为导致数据不一致的错误打开了大门。

其他一些观察结果:

  • 如果level_id值得存储在members中,那么总经验值也可以。如果您缓存level_id但仍需要每次都读取所有points条记录以获得总数,那么您将获得两个世界中最差的记录。当然,这取决于您的应用程序。
  • 将历史存储在points中是个好主意,但它并没有告诉你太多。我可能会将其命名为achievementspoint_events,并存储有关获得积分的原因的一些信息。
  • 在某些地方使用points而在其他地方使用experience_needed并不理想。我会选择一个名字并在任何地方坚持使用它:experiencepointsxp_points或wahtever。

最后:你想要在数据库设计(和数据建模,应该首先)上做得更好,但是你是否存储或计算level_id可能不会直到/除非你的系统非常庞大且性能受限,否则问题太多了。所以在这一点上不要太担心。立即构建,稍后进行优化。