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_id
– alliance_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 “
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 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
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 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!