Я собираюсь мягко не согласиться со всеми и сказать, что реляционный подход здесь разумен. Здесь интересно то, что предметы могут иметь несколько ролей. Основная проблема заключается в том, что отображение между этим реляционным макетом и компоновкой OO в коде не будет казаться «естественным», но я думаю, что на стороне базы данных несколько ролей можно выразить чисто (без странных кодировок или избыточности, просто объединяет) ,
Первое, что нужно решить, это то, какая часть данных относится к конкретному элементу и какая часть используется всеми элементами данного типа.
Вот что я бы сделал, если бы все данные относились к конкретному элементу:
// ITEMS table: attributes common to all items
item_id | name | owner | location | sprite_id | ...
1 | Light Saber | 14 (Tchalvek) | 381 (Tchalvek house) | 5663 | ...
// WEAPONS table: attributes for items that are weapons
item_id | damage | damage_type | durability | ...
1 | 5 | sharp | 13 | ...
// LIGHTING table: attributes for items that serve as lights
item_id | radius | brightness | duration | ...
1 | 3 meters | 50 | 8 hours | ...
В этом дизайне каждый элемент находится в таблице Предметов вместе с атрибутами, которые есть у всех (или большинства) предметов. Каждая дополнительная роль, которую может играть элемент, представляет собой отдельный стол.
Если вы хотите использовать его в качестве оружия, вы должны найти его в таблице оружия. Если он там, то его можно использовать как оружие. Если его там нет, его нельзя использовать в качестве оружия. Наличие записи говорит вам, является ли это оружием. И если он там, все его специфичные для оружия атрибуты хранятся там. Поскольку эти атрибуты хранятся непосредственно, а не в какой-то закодированной форме, вы сможете выполнять с ними запросы / фильтры. (Например, для страницы показателей вашей игры вы можете объединить игроков по типу урона от оружия, и вы сможете сделать это с некоторыми объединениями и типом группового повреждения.)
Элемент может иметь несколько ролей и находиться в нескольких таблицах для конкретных ролей (в этом примере - как оружие, так и освещение).
Если это просто логическое значение типа «это удерживаемо», я бы положил его в таблицу «Предметы». Возможно, стоит кешировать «это оружие» и т. Д. Там, чтобы вам не приходилось искать оружие и другие таблицы ролей. Тем не менее, это добавляет избыточность, поэтому вы должны быть осторожны, чтобы синхронизировать его.
Рекомендация Ари о наличии дополнительной таблицы для каждого типа также может быть использована с этим подходом, если некоторые данные не изменятся для каждого элемента. Например, если урон от оружия не меняется для каждого предмета, но роли по-прежнему различаются для каждого предмета, вы можете выделить общие атрибуты оружия в таблицу:
// WEAPONS table: attributes for items that are weapons
item_id | durability | weapon_type
1 | 13 | light_saber
// WEAPONTYPES table: attributes for classes of weapons
weapon_type_id | damage | damage_type
light_saber | 5 | energy
Другой подход заключается в том, что роли, выполняемые предметами, не различаются по предметам, а только по типам предметов. В этом случае вы поместите item_type в таблицу Items и сможете хранить свойства, такие как «Является ли это оружием» и «Держится ли оно» и «Является ли это светом» в таблице ItemTypes. В этом примере я также делаю имена элементов не меняющимися для каждого элемента:
// ITEMS table: attributes per item
item_id | item_type | owner | location
1 | light_saber | 14 (Tchalvek) | 381 (Tchalvek house)
// ITEMTYPES table: attributes shared by all items of a type
item_type | name | sprite_id | is_holdable | is_weapon | is_light
light_saber | Light Saber | 5663 | true | true | true
// WEAPONTYPES table: attributes for item types that are also weapons
item_type | damage | damage_type
light_saber | 5 | energy
Вероятно, что типы предметов и типы оружия не меняются во время игры, так что вы можете просто загрузить эти таблицы в память и посмотреть эти атрибуты в хеш-таблице, а не в соединении с базой данных.