Database
 sql >> Datenbank >  >> RDS >> Database

MMO-Spiele und Datenbankdesign

Seien wir ehrlich:Wir alle lieben es, Spiele zu spielen, besonders auf unseren Computern. Bis sich das Internet verbreitete, spielten die meisten von uns selbst Computerspiele, normalerweise gegen KI-Gegner. Es hat Spaß gemacht, aber sobald Sie erkannt haben, wie die Spielmechanik funktioniert, hat das Spiel den größten Teil seiner Magie verloren.

Die Entwicklung des Internets hat Spiele ins Internet verlagert. Jetzt können wir gegen menschliche Gegner spielen und unsere Fähigkeiten gegen ihre testen. Kein auswendig gelerntes Gameplay mehr!

Dann tauchten Massive Multiplayer Online (MMO)-Spiele auf und veränderten alles. Tausende von Spielern fanden sich in denselben Spieluniversen wieder, wetteiferten um Ressourcen, verhandelten, handelten und kämpften. Um solche Spiele zu ermöglichen, wurde eine Datenbankstruktur benötigt, die alle relevanten Informationen speichern konnte.

In diesem Artikel werden wir ein Modell entwerfen, das die häufigsten Elemente von MMO-Spielen enthält. Wir werden besprechen, wie man es verwendet, seine Einschränkungen und mögliche Verbesserungen.

Eine Einführung in Datenmodelle für MMO-Spiele

Heutzutage gibt es viele sehr beliebte MMO-Spiele, die alle möglichen Szenarien beinhalten. Ich werde mich hier auf Strategiespiele wie Ogame konzentrieren , Travian , Sparta :Krieg der Imperien und Imperia Online . Bei diesen Spielen geht es mehr um Planung, Aufbau und Strategiefindung und weniger um direkte Aktionen.

MMO-Spiele sind in verschiedenen Universen angesiedelt, unterscheiden sich visuell und verwenden mehr oder weniger unterschiedliche Spieloptionen. Dennoch sind einige Ideen die gleichen. Die Spieler konkurrieren um Orte, kämpfen für sie und bilden Allianzen mit (und gegen) anderen Spielern. Sie bauen Strukturen auf, sammeln Ressourcen und erforschen Technologien. Sie bauen Einheiten (wie Krieger, Panzer, Händler usw.) und nutzen sie, um mit Verbündeten Handel zu treiben oder mit Gegnern zu kämpfen. All das muss in unserer Datenbank unterstützt werden.

Wir können uns diese Spiele als Online-Brettspiele mit vielen indizierten Quadraten vorstellen. Jedem Feld können viele verschiedene Aktionen zugeordnet werden; Einige Aktionen beinhalten mehrere Quadrate – z. wenn wir Einheiten oder Ressourcen von einem Ort zum anderen bewegen.




Die Datenbank ist in fünf Hauptbereiche unterteilt:

  • Players / Users
  • Alliances
  • Locations and Structures
  • Research and Resources
  • Units

Die verbleibenden sieben nicht gruppierten Tabellen beziehen sich auf Einheiten und beschreiben die Position der Einheiten und Bewegungen im Spiel. Wir werden uns jeden dieser Bereiche genauer ansehen, beginnend mit Spielern und Allianzen .

Spieler und Allianzen

Ohne Zweifel sind die Spieler der wichtigste Teil eines jeden Spiels.

Der player Tabelle enthält eine Liste aller registrierten Spieler, die an einer Spielinstanz teilnehmen. Wir speichern die Benutzernamen, Passwörter und Bildschirmnamen der Spieler. Diese werden im user_name gespeichert , password , und nickname Attribute bzw.

Neue Benutzer müssen bei der Registrierung eine E-Mail-Adresse angeben. Ein Bestätigungscode wird generiert und an sie gesendet, auf den sie antworten. Wir werden das confirmation_date aktualisieren -Attribut, wenn der Benutzer seine E-Mail-Adresse bestätigt. Diese Tabelle hat also drei eindeutige Schlüssel:user_name , nickname und email .

Jedes Mal, wenn sich ein Benutzer anmeldet, wird ein neuer Datensatz in login_history Tisch. Alle Attribute in dieser Tabelle sind selbsterklärend. Die logout_time ist spezifisch. Es kann NULL sein, wenn die aktuelle Sitzung des Benutzers aktiv ist oder wenn Benutzer das Spiel aufgrund technischer Probleme beenden (ohne sich abzumelden). In den login_data -Attribut speichern wir Anmeldedaten wie den geografischen Standort eines Spielers, die IP-Adresse sowie das Gerät und den verwendeten Browser.

Bei den meisten MMO-Spielen können wir mit anderen Spielern zusammenarbeiten. Eine der Standardformen der Spielerkooperation ist die Allianz. Spieler teilen ihre „privaten Daten“ im Spiel (Online-Status, Pläne, Standorte ihrer Städte und Kolonien usw.) mit anderen, um von Aktionen der Verbündeten zu profitieren und aus reinem Spaß daran.

Die alliance Tabelle speichert grundlegende Informationen über Spielallianzen. Jeder hat einen eindeutigen alliance_name die wir speichern. Wir haben auch ein Feld, date_founded , die speichert, wann die Allianz gegründet wurde. Wenn eine Allianz aufgelöst wird, speichern wir diese Informationen im date_disbanded Attribut.

Das alliance_member Tabelle verbindet Spieler mit Allianzen. Spieler können derselben Allianz mehr als einmal beitreten und sie verlassen. Aus diesem Grund wird die player_idalliance_id Paar ist kein eindeutiger Schlüssel. Wir bewahren Informationen darüber auf, wann ein Spieler der Allianz beitritt und wann (falls) er sie verlässt im date_from und date_to Felder. Die membership_type_id -Attribut ist ein Verweis auf membership_type Wörterbuch; Es speichert die aktuelle Ebene der Spielerrechte in der Allianz.

Die Rechte der Spieler in einer Allianz können sich im Laufe der Zeit ändern. Die membership_actions , membership_type und actions_allowed Tabellen definieren zusammen alle möglichen Rechte für Allianzmitglieder. Dieses Modell erlaubt es Spielern nicht, ihre eigenen Rechte in einer Allianz zu definieren, aber das könnte leicht genug erreicht werden, indem neue Datensätze im membership_type Wörterbuch und Speichern von Informationen darüber, mit welchen Allianzen sie verbunden sind.

Fazit:Die in diesen Tabellen hinterlegten Werte werden von uns bei der Ersteinrichtung definiert; sie werden sich nur ändern, wenn wir neue Optionen einführen.

Der membership_history Tabelle speichert alle Daten zu den Rollen oder Rechten von Spielern innerhalb einer Allianz, einschließlich des Bereichs, in dem diese Rechte gültig waren. (Zum Beispiel könnte er einen Monat lang „Anfänger“-Berechtigungen haben und von diesem Zeitpunkt an dann „Vollmitgliedschaft“.) Das date_to -Attribut ist NULL-fähig, da derzeit aktive Rechte noch nicht beendet sind.

Die membership_actions Wörterbuch enthält eine Liste aller Aktionen, die Spieler in einer Allianz durchführen können. Jede Aktion hat ihren eigenen action_name und die Spiellogik ist um diese Namen herum aufgebaut. Wir können Werte wie "Mitgliederliste anzeigen" erwarten , "Status der Mitglieder anzeigen" und "Nachricht senden" hier.

Der membership_type Wörterbuch enthält die eindeutigen Namen der im Spiel verwendeten Aktionsgruppen. Der actions_allowed Tabelle ordnet Aktionen Mitgliedschaftsarten zu. Jede Aktion kann nur einmal einem Typ zugeordnet werden. Daher die membership_action - membership_type Paar bildet den eindeutigen Schlüssel für diese Tabelle.

Standorte und Strukturen

Spielorte sind Bereiche, in denen Spieler Ressourcen sammeln und Gebäude und Einheiten bauen. Einige Spiele haben einen vordefinierten Bereich möglicher Standorte, während andere es Benutzern ermöglichen, ihre eigenen Standorte zu definieren.

In einem 3D-Raum können Orte mit [x:y:z]-Koordinaten definiert werden. Wenn ein Spiel einen vordefinierten Bereich hat, erlaubt es Spielern möglicherweise nicht, für alle drei Achsen einen Ort außerhalb des Bereichs [0:1000] zu verwenden, daher sind wir auf einen Bereich von 1000 * 1000 * 1000 beschränkt.

Andererseits möchten wir Spielern vielleicht erlauben, die genauen Koordinaten ihres neuen Standorts einzugeben – z. [1001:2073:4] – und wir wollen, dass das Spiel es für sie verarbeitet.

Wir führen eine Liste aller Standorte, die in einer Instanz unseres Spiels im location Tisch. Jeder Standort hat seinen eigenen Namen, aber die Namen sind nicht eindeutig. Andererseits die coordinates -Attribut darf nur eindeutige Werte enthalten. Ortskoordinaten werden als Textwerte gespeichert, sodass wir Koordinaten für 3D-Spiele als [112:72:235] speichern können. Koordinaten für 2D-Spiele können als <1102:98> gespeichert werden.

In einigen Spielen haben Orte eine Reihe von Quadraten, die zur Unterbringung von Gebäuden oder Einheiten verwendet werden. Wir behalten diese Informationen in der dimension Attribut, das ein Textfeld ist. Eine Dimension kann einfach eine Anzahl von Quadraten in einem 2D- oder 3D-Raster sein. Die player_id -Attribut speichert Informationen über den aktuellen Eigentümer dieses Standorts. Es kann NULL sein, wenn Orte vordefiniert sind und Spieler darum konkurrieren, sie zu besetzen.

Die structure Die Tabelle enthält eine Liste aller Strukturen, die wir an verschiedenen Spielorten bauen können. Strukturen stellen Verbesserungen dar, die es uns ermöglichen, bessere Einheiten zu produzieren, neue Arten von Forschung durchzuführen, mehr Ressourcen zu produzieren usw. Jede Struktur, die im Spiel verwendet wird, hat ihren eigenen einzigartigen structure_name . Einige mögliche structure_name Werte sind „Farm“, „Erzbergwerk“, „Solaranlage“ und „Forschungszentrum“.

Wir können davon ausgehen, dass jede Struktur mehrmals aktualisiert wird, daher speichern wir auch Informationen über ihr aktuelles Level. Jedes Upgrade verbessert die Leistung der Strukturen, sodass mehr Ressourcen produziert werden oder wir neue Funktionen im Spiel nutzen können. Wir können das maximale Upgrade-Level nicht im Voraus kennen, also definieren wir alle Level-bezogenen Dinge (Kosten, Upgrade-Zeit und Produktion) mit Formeln. Alle in der Datenbank gespeicherten Formeln sind der Kern der Spielmechanik, und ihre Anpassung ist entscheidend für die Spielbalance und das Gameplay im Allgemeinen.

Das ist auch bei der upgrade_time_formula der Fall Attribut. Ein Beispielwert für dieses Feld ist * 30 min” , wobei stellt das Level dar, auf das wir upgraden möchten.

In den meisten Fällen gibt es Anforderungen, die erfüllt werden müssen, bevor Spieler bestimmte Aktionen ausführen können. Vielleicht müssen wir eine definierte Menge an Forschung abschließen, bevor wir neue Strukturen aufbauen können oder umgekehrt. Wir speichern das zum Aufbau von Strukturen benötigte Forschungsniveau in prerequisite_research Tisch. Beziehungen und die Strukturebene, die zum Starten verschiedener Recherchen erforderlich sind, werden in prerequisite_structure Tisch. In beiden Tabellen sind die Fremdschlüssel research_id und structure_id werden gepaart, um einen eindeutigen Schlüssel zu bilden. Der level_required Das Attribut ist der einzige Wert.

Diese beiden Tabellen, prerequisite_research und prerequisite_structure , bilden auch den Kern des Spiels.

Für jede Struktur definieren wir eine Liste von Voraussetzungen:andere Strukturen und ihre Mindeststufen, die die Spieler haben müssen, um mit dem Bau beginnen zu können. Wir speichern diese Daten in structure_required Tisch. Hier structure_id repräsentiert die Struktur, die wir bauen wollen; structure_required_id ist ein Verweis auf die vorausgesetzte(n) Struktur(en) und level ist das erforderliche Niveau.

Die structure_built Tabelle speichert Informationen über aktuelle Strukturebenen an einem bestimmten Ort. Das upgrade_ongoing Das Attribut wird nur gesetzt, wenn gerade ein Upgrade durchgeführt wird, während upgrade_end_time -Attribut enthält einen Zeitstempel, sobald das Upgrade abgeschlossen ist.

Die structure_formula Tabelle bezieht sich auf Strukturen und Ressourcen. Das Fremdschlüsselpaar zu dieser Tabelle bildet ihren eindeutigen Schlüssel. Diese Tabelle hat auch zwei Textattribute, die Formeln mit als Parameter enthalten. Wir definieren diese Formeln, eine für die Kosten und die andere für die Ressourcengenerierung, in der Datenbank. Sie ähneln der upgrade_time_formula . Wir brauchen sie, weil wir die Ressourcen definieren müssen, die für den Aufbau jeder Struktur aufgewendet werden. Wir müssen auch die Ressourcenproduktion nach dem Upgrade definieren, wenn die Struktur Ressourcen generiert (d. h. die Erzmine produziert * 20 Erz pro Tag).

Forschung und Ressourcen

Forschung (oder Technologien) in Spielen sind normalerweise für die Erstellung anderer Funktionen erforderlich. Ohne ein bestimmtes Forschungsniveau können keine neuen Strukturen oder Einheitentypen gebaut werden. Forschung kann auch ihre eigenen Anforderungen haben. Eine der häufigsten ist die Ebene einer bestimmten Struktur, die normalerweise als „Forschungslabor“ bezeichnet wird. Oder vielleicht müssen die Spieler ein bestimmtes Forschungsniveau abschließen, bevor sie mit einer neuen Forschung beginnen können. Alle diese Anforderungen werden in diesem Abschnitt behandelt. Unten finden wir das Datenmodell für Forschung und Ressourcen:

Die research Tabelle enthält eine Liste aller möglichen Forschungsaktionen in unserem Spiel. Es verwendet die gleiche Logik wie die structure Tisch. Der research_name Das Attribut ist der eindeutige Schlüssel der Tabelle, während die upgrade_time_formula Das Feld enthält eine Textdarstellung der Formel für den Forschungszeitbedarf mit als Parameter. Alle für Upgrades erforderlichen Ressourcen sind in der upgrade_formula definiert in der research_formula Tabelle.

Wie bei Strukturen definieren wir die Liste aller anderen Forschungen und ihrer Ebenen, die abgeschlossen sein müssen, bevor wir eine andere Art von Forschung beginnen können. Wir speichern diese Daten im research_required Tabelle, wobei research_id stellt die gewünschte Forschung dar; research_required_id ist ein Verweis auf die vorausgesetzte Forschung und level ist das erforderliche Niveau.

Forschung bezieht sich auf einzelne Spieler und für jeden Spieler – Recherche ch-Paar müssen wir das aktuelle Forschungsniveau eines Spielers und alle laufenden Upgrade-Status speichern. Wir speichern diese Informationen unter Verwendung des research_level Tabelle auf die gleiche Weise, wie wir die structure_built Tabelle.

Ressourcen wie Holz, Erz, Edelsteine ​​und Energie werden abgebaut oder gesammelt und später zum Bau von Gebäuden und anderen Verbesserungen verwendet. Wir speichern eine Liste aller In-Game-Ressourcen in der resource Wörterbuch. Das einzige Attribut hier ist der resource_name Feld, und es ist auch der eindeutige Schlüssel der Tabelle.

Um die aktuelle Menge an Ressourcen an jedem Standort zu verfolgen, verwenden wir den resources_on_location Tisch. Auch hier wird ein Fremdschlüsselpaar (resource_id und location_id ) bildet den eindeutigen Schlüssel der Tabelle, während die number -Attribut speichert die aktuellen Ressourcenwerte.

Einheiten und Bewegungen

Ressourcen werden verwendet, um Einheiten zu produzieren. Einheiten können verwendet werden, um Ressourcen zu transportieren, andere Spieler anzugreifen oder allgemein zu plündern und zu verbrennen.

Die Liste der in unserem Spiel verwendeten Einheitentypen ist in unit Wörterbuch mit nur einem Wert, unit_name; dieses Attribut ist der eindeutige Schlüssel dieser Tabelle. Einige gebräuchliche Spieleinheiten sind „Schwertkämpfer“, „Schlachtkreuzer“, „Greif“, „Düsenjäger“, „Panzer“ usw.

Wir müssen jede Einheit mit spezifischen Eigenschaften beschreiben. Eine Liste aller möglichen Merkmale ist im characteristic Wörterbuch. Der characteristic_name Feld enthält einen eindeutigen Wert. Werte in diesem Feld könnten beinhalten:„Angriff“, „Verteidigung“ und „Trefferpunkte“. Wir weisen Einheiten Eigenschaften zu, indem wir unit_characteristic Beziehung. Das Fremdschlüsselpaar von unit_id und characteristic_id bilden den eindeutigen Schlüssel der Tabelle. Wir verwenden nur ein Attribut, value , um den gewünschten Wert zu speichern.

Die research_unit Die Tabelle enthält eine Liste aller Forschungsaktivitäten, die abgeschlossen sein müssen, bevor wir mit der Produktion eines bestimmten Gerätetyps beginnen können. Die unit_cost Tabelle definiert die Ressourcen, die zur Herstellung einer einzelnen Einheit benötigt werden. Beide Tabellen haben eindeutige Schlüssel, die aus dem Fremdschlüsselpaar (research_id oder resources_id kombiniert mit unit_id ) und ein Wertefeld (cost und level_required ).

Und jetzt der lustige Teil. Produzieren macht Spaß, aber das Bewegen von Einheiten und Handeln ist noch besser. Wir haben bereits die unit Tabelle, aber wir behalten sie hier, weil sie mit anderen Tabellen zusammenhängt.

Entweder sind Einheiten an einem Ort stationiert oder sie bewegen sich zwischen den Orten. Hinzufügen der player_id bestimmt, wem entweder der Standort oder die Gruppe gehört, die sich zwischen den Standorten bewegt.

Wenn Einheiten nur an dem angegebenen Ort stationiert sind, speichern wir diesen Ort und die Anzahl der dort stationierten Einheiten. Dazu verwenden wir den units_on_location Tabelle.

Wenn Einheiten nicht stationiert sind, bewegen sie sich. Wir müssen ihren Abfahrtsort und ihr Ziel speichern. Außerdem müssen wir mögliche Aktionen während der Bewegungen definieren. Alle diese Aktionen werden im movement_type Wörterbuch. Der type_name Attribut ist eindeutig, während allows_wait Das Attribut bestimmt, ob eine Aktion das Warten am Zielpunkt erlaubt.

Wir können einen einzelnen Einheitentyp bewegen, aber in fast allen Fällen werden wir viele Einheiten verschiedener Einheitentypen bewegen. Diese Gruppe teilt gemeinsame Daten und wir speichern sie im group_movement Tisch. In dieser Tabelle definieren wir die folgenden Elemente:

  • der Spieler, der diese Aktion initiiert hat
  • der Aktionstyp
  • der Ausgangspunkt
  • der Zielpunkt
  • die arrival_time am Ziel
  • die return_time zum Ausgangspunkt
  • die wait_time am Ziel

Die return_time Das Attribut kann NULL sein, wenn es sich um eine einfache Fahrt handelt, und wait_time wird vom Spieler bestimmt. Zu einer Gruppe gehörende Einheiten werden durch Werte definiert, die in units_in_group Tisch. Das Fremdschlüsselpaar units_id und group_moving_id bildet den eindeutigen Schlüssel der Tabelle. Die Anzahl der Einheiten gleichen Typs innerhalb einer Gruppe wird in number definiert Attribut.

Jede Bewegung kann Ressourcen von einem Ort zum anderen transportieren. Daher definieren wir eine Viele-zu-Viele-Beziehung zwischen group_movement und die resources Tische. Neben den Primär- und Fremdschlüsseln werden die resources_in_group Tabelle enthält nur die number Attribut. Dieses Feld speichert die Menge an Ressourcen, die Spieler vom Startpunkt zu ihrem Ziel bewegen.

In den meisten Fällen können Spieler andere anrufen, um sich ihrem Abenteuer anzuschließen. Um dies zu unterstützen, verwenden wir zwei Tabellen:allied_movement und allied_groups . Ein Spieler wird eine gemeinsame Aktion initiieren, und das wird einen neuen Rekord in der allied_movement Tisch. Alle Gruppen von Einheiten, die an einer alliierten Aktion teilnehmen, werden durch Werte definiert, die in allied_groups Tisch. Jede Gruppe kann nur einmal einer verbündeten Aktion zugeordnet werden, Fremdschlüssel bilden also den eindeutigen Schlüssel dieser Tabelle.

Dieses Modell gibt uns die Grundstruktur, die wir brauchen, um ein MMO-Strategiespiel aufzubauen. Es enthält die wichtigsten Spielfunktionen:Orte, Gebäude, Ressourcen, Forschung und Einheiten. Es verknüpft sie auch, lässt uns Voraussetzungen in der Datenbank definieren und speichert den größten Teil der Spiellogik ebenfalls in der Datenbank.

Nachdem diese Tabellen gefüllt sind, ist der Großteil der Spiellogik definiert und wir würden nicht erwarten, dass neue Werte hinzugefügt werden. Fast jede Tabelle hat einen eindeutigen Schlüsselwert, entweder einen Feature-Namen oder ein Fremdschlüsselpaar. Das Ändern der Einheiteneigenschaften und der Produktions-/Kostenformeln ermöglicht es uns, die Spielbalance in der Datenbankebene zu ändern.

Wie würden Sie dieses Modell ändern? Was gefällt dir, was würdest du anders machen? Sag es uns im Kommentarbereich!