Multiplayer Modus  C   P 

Die Netzwerk-Engine verwendet einen Client/Server Mechanismus, um mehrere Spieler über ein lokales Netzwerk oder das Internet zu verbinden. Einer der verbundenen PCs - oder präziser, eines der laufenden Spielprogramme - ist der Server, der das Spiel steuert. Alle anderen sind Clients, die den einzelnen Spielern zugeordnet sind.

Die Engine übernimmt das Senden und Empfangen des Levelstatus von alleine, ohne dass ein Skript dafür nötig wäre. Auf diese Weise ist jedes Spiel, das Sie erstellen, automatisch ein Netzwerkspiel, sobald die Engine im Server- oder Client-Modus gestartet wurde. Ein Vorhersage-Algorithmus (Dead Reckoning) sorgt für glatte Bewegungen der Entities und minimiert die erforderliche Bandbreite. Alles andere außer der Aktualisierung des Levelzustands - zum Beispiel die Eingaben der Spieler per Tastatur oder Joystick, oder Textstrings zum Chatten oder Austausch von Nachrichten - muss per Sendefunktion gesendet werden. Daher erfordert das Schreiben eines Skripts für ein Netzwerkspiel etwas zusätzlichen Code im Skript. Ein Beispiel eines einfachen 3D-Netzwerkspieles finden Sie im Workshop 25 des lite-C-Tutorials. Ein 2D-Multiplayer-Beispiel - pong_multiplayer.c findet sich im Beispielordner (samples).

Einige Tipps zum Programmieren eines Multiplayer-Spieles

Um ein Multiplayer Netzwerk einzurichten, suchen Sie zuerst den Server-PC aus. Der Server übernimmt den Löwenanteil der Kommunikation und sollte auf der Maschine mit der schnellsten Netzwerkverbindung laufen. Er muss zuerst gestartet werden, entweder mit -sv in der Befehlszeile oder dem session_open-Befehl. Der Server kann gleichzeitig ein Klient sein - so brauchen Sie keinen extra PC für ihn. Läuft der Server, können sich jederzeit weitere Klienten ein- oder ausloggen indem sie dieselbe Anwendung mit der Kommandozeilenoption -cl, starten oder den Befehl session_connect verwenden. Die Commercial-Edition  C  ist auf einen Server und 8 Klienten pro Session begrenzt, die Pro-Edition  P  ist nicht limitiert.

Sobald die Verbindung steht, wechselt die vorgegebene Variable connection von 0 zu 1, 2, oder 3, je nachdem ob die Engine als Server, Klient, oder beides läuft. Normalerweise läuft dasselbe Skript auf Server und Klient und damit beide dieselben globalen Variablen und dieselben Entity-Funktionen teilen können. Das Programm kann durch die connection-Variable zwischen Server und Client Modus unterscheiden, und entsprechend unterschiedlichen Code ausführen. Eine beliebige Anzahl von Spiel-Sessions kann auf dem gleichen lokalen Netzwerk oder der gleichen Internetadresse laufen. Ein Client verbindet sich automatisch mit der Session mit dem gleichen Namen, der defaultmäßig dem Namen des Skripts entspricht. Auch hat jeder Klient einen individuellen Playernamen, der entweder durch die Kommandozeilenoption -pl angegeben, per Skript (player_name) erstellt oder von der Engine generiert wird.

 P Mehrere Server für das gleiche Spiel, aber verschiedene Level, können auf dem gleichen oder mehreren PCs laufen. Unterschiedliche Session-Namen und Portadressen müssen in diesem Fall verwendet werden. Ein Client kann von einem zum anderen Server per session_connect Anweisung wechseln. Auf diese Weise können riesige Level in verschiedene Zonen aufgeteilt werden, die auf verschiedenen Server-Belegstellen, oder sogar verschiedenen Rechnern laufen. Um zu Überwachen, was auf einem zzugeordneten Server ohne Klient geschieht, können Sie ein Konsolenfenster aktivieren, das jeden Server-Event ausdruckt (Kommandozeilenoption -sv -diag).

Sämtliche Kommunikation wird normalerweise über das Updaten globaler Variablen, von Textstrings und Entity-Eigenschaften zwischen Servern und Klienten gehandhabt. Zum Senden gibt es mehrere send_... Anweisungen. Das Empfangen einer Nachricht oder bestimmte Multiplayer-Ereignisse lösen auf dem empfangenden Rechner eine Event-Funktion aus. Wenn zum Beispiel ein Klient sich mit dem Server verbindet, wird der vordefinierte on_server-Event auf dem Server ausgelöst, event_type wird auf EVENT_JOIN gesetzt und ein Stringpointer mit dem Client-Namen wird der Eventfunktion als Parameter übergeben. Dieser Mechanismus ist mit der Verarbeitungsweise von Entity-Events identisch .

Für wesentliche Botschaften wie das Beitreten oder das Übermitteln von Variablen oder Strings wird ein betriebssicheres Protokoll benutzt. Ein schnelleres aber nicht sicheres Protokoll wird hingegen für oft wiederholte Botschaften wie Entity-Updates verwendet. Das Protokoll, die Paketgröße und weitere Parameter können durch die verschiedenen dplay_.. Variablen angepasst und modifiziert werden, normalerweise ist deren Default-Einstellung jedoch die Beste.

Per Default laufen die Entity-Aktionen nur auf dem Server und der updatet die Klienten permanent in Zeitintervallen, die über dplay_entrate angegeben werden, mit sämtlichen sichtbaren Entity-Eigenschaften. Man könnte versucht sein, dplay_entrate so niedrig wie möglich zu setzen, um weichere Entity-Bewegungen zu erreichen. Die mag bei einen LAN funktionieren, ist jedoch für Online-Games nicht zu empfehlen. Um über das Internet zu spielen, sollte die Bandbreite minimiert sein indem man dplay_entrate hoch hält, Entity-Effekte, Animationen oder Sounds aber Seiten der Klienten kontrolliert. Die einfachste Methode hierfür ist es, durch Setzen von dplay_localfunction vor dem Laden, Entity-Aktionen sowohl auf dem Server als auch auf den Klienten laufen zu lassen und sie in Abhängigkeit des connection-Status´ verschiedene Dinge tun zu lassen. Alternativ hierzu kann der Server eine spezielle Klientenfunktion für eine Entity starten (proc_client). Wird ein bestimmter Entity-Parameter wie entity.frame auf dem Klienten gesteuert, muß sein entsprechender NOSEND_.. -Flag gesetzt sein, damit dieser Parameter vom automatischen Update ausgeschlossen ist.

Der Vorhersage-Algorithmus (Dead Reckoning) berechnet linear Rotation, Geschwindigkeit und Beschleunigung der Entities voraus. Dies glättet die Bewegung der Entities auf langsamen Client/Server Systemen mit hoher Latenzzeit. Aber plötzliche Richtungsänderungen, wie das Anhalten eines Fahrstuhls oder das Abprallen einer Kugel, können den Algorithmus verwirren, was zu einem Überschreiten der Grenzen führen kann. Um dies zu verhindern, sollte Sie die ent_sendnow-Anweisung verwenden, wenn sich Geschwindigkeit oder Rotation einer Entity abrupt ändert.

Globale Variablen und Strings werden nicht automatisch zwischen Server und Client synchronisiert. Daher können Server und Client für diese unterschiedliche Werte enthalten, falls sie nicht ausdrücklich über die Anweisungen send_var und send_string synchronisiert werden. Hier sollte man mit Sorgfalt vorgehen und wirklich nur veränderte Werte senden, andernfalls verschwenden Sie Bandbreite.

Wurde eine Entity von einem Klient mittels ent_create Anweisung erstellt, wird diese auf dem Server in Erscheinung treten und ihre Aktion starten. Jeder Client kann per send_skill-Anweisungen seine eigene Spieler-Entity kontrollieren - normalerweise werden auf diesem Wege Keyboard- und Joystick-Eingaben zum Server übermittelt und dort zum Bewegen der Player-Entity des betreffenden Clienten verwendet. Unterbricht der Client die Verbindung, kann er keine weiteren Skillwerte mehr senden, und die Player-Entity verharrt bewegungslos. Dann kann die Entity mithilfe von event_disconnect entfernt werden.

Unter Client/Server Protocol finden Sie eine Beschreibung des Multiplayer-Protokolls der Engine.

Tipps zum Schreiben von guten Online-Spielen

Online-Games müssen zwei grundsätzliche Internet-Flaschenhälse überwinden: Bandbreite und Verzögerungszeit. In dieser Hinsicht gleicht das Internet einem Förderband. Die Bandbreite stellt die Breite des Bandes dar und bestimmt wie viele Daten sich gleichzeitig darauf befördern lassen. Die Verzögerungszeit ist die Geschwindigkeit des Bandes und legt fest wie lange die Clienten darauf warten müssen bis die Meldungen vom Server ankommen und umgekehrt.

Einige Bemerkungen zu MMORPGs

Eine oft gestellte Frage: Bitte erklärt mir, wie man mit Gamestudio ein MMORPG macht!

Ein Online-Spiel mit Tausenden von Spielern gehört zu den ambitioniertesten Spieleprojekten. Ein MMORPG besteht aus einer großen in Zonen aufgeteilten Spielwelt, die über mehrere Server verteilt ist. Ein solcher Server-Park besteht aus einem Portal-Server, mehreren Zone-Servern und einem oder mehreren Datenbank-Servern. Die Spielerdaten werden auf dem Datenbank-Server gespeichert - beispielsweise in einer MySQL-Datenbank - und von den Zone-Servern upgedated. Der Zugriff von den Zone-Servern auf die Datenbank muß durch ein Skript oder eine auf den Datenbank-Typus und Anwenderdatenstruktur zugeschnittene DLL erfolgen. Die Game-Engine kümmert sich um die Clients und das Zone-Gameplay. Der Client schaltet mit der Funktion session_connect zwischen den Zonen hin und her.

Wie Sie der obigen Darstellung entnehmen können, ist das Erstellen eines MMORPG - egal mit welcher Engine - definitiv kein Hobby-Projekt. Es erfordert gute Kenntnisse der Struktur eines Multiserver-Systems und ebenso gute Programmierkenntnisse (oder den eisernen Willen, sich diese Kenntnisse anzueignen). Die A7-Netzwerkfeatures sind einfach zu handhaben, eine massive Multiplayer-Onlinewelt aber verlangt trotzdem eine Menge an Code, ein gutes Team und, nicht zu vernachlässigen: eine solide Finanzierung. Oft ist es sinnvoll, als Prototyp zuerst eine einfache Ein-Server-Version des Games zu erstellen und damit die Finanzierung für eine Datenbanklizenz und einen Serverpark zu akquirieren.

► Aktuelle Version Online