Version 2.0!
Features
Tutorials
Files
Glossary
Projects
Contact
Links
Message Board
Extras
LuckyCam
Old News
Sign Guestbook
View Guestbook
VB Horoscope
VB Photo Album
.
ATTENTION READERS! Lucky's VB Gaming Site is no longer active. For updated game programming information and tutorials, please visit The Game Programming Wiki!

Nachrichten während des Spieles verschicken

Vegetarier wegschauen. Wir werden uns jetzt mit den Eingeweiden von DPlay beschäftigen: Nachrichten. Das ist nichts für jemanden mit schwachem Herz! Holt eure Kochtöpfe, wir kochen uns einen schönen Eintopf saftigen Codes!

Mhm.... DirectPlay Suppe.

(okok... zugegeben, die Übersetzung ist ein bißchen... "strange" ;-) - d.Ü.)

Es gibt zwei Arten von Nachrichten, die uns begegnen werden, zum einen "benutzerdefinierte" Nachrichten und "system" Nachrichten. Eine benutzerdefinierte Nachricht müssen wir selbst erstellen, um spielrelevante Informationen zwischen den Spielern auszutauschen. Eine system Nachricht erstellt DPlay selbst, um die anderen DPlay -Objekte aktuell zu halten.

Beispiel: Wir benutzen eine benutzerdefinierte Nachricht um die Bewegung des Balles an die zwei Spieler eines Spieles von NetPONG zu übermitteln.
Eine Systemnachricht informiert den Host z.B. darüber, daß dem Spiel ein neuer Spieler beigetreten ist.

Systemnachrichten werden von DPlay automatisch zu geeigneten Zeitpunkten gesendet, die benutzerdefinierten können wir aber senden wann immer wir wollen:
 

Const MSG_CHATTEXT = 0
Dim dpMsg As DirectPlayMessage  'Create a message object

    Set dpMsg = dp.CreateMessage    
    dpMsg.WriteLong MSG_CHATTEXT
    dpMsg.WriteString strChatText
    dp.SendEx lngPlayerID, DPID_ALLPLAYERS, DPSEND_GUARANTEED, dpMsg, 0, 0, 0
Gib das DirectPlayMessage Objekt ein. Initialisiere ein neues mit der Methode DirectPlay4.CreateMessage und dann kann es los gehen. . DirectPlayMessage-Objekte  stellen Methoden zur Verfügung, die uns erlauben, Daten verschiedener Arten zu "schreiben" (Long, Integers, Strings, etc.). Im oben gezeigten Code schreiben wir zuerst eine Long-Variable MSG_CHATTEXT. Es ist üblich, am Anfang einer Nachricht ein Long zu schreiben, die die Art der Nachricht angibt (du mußt diese Konstanten selbst erstellen und festsetzen!), um sie so sortieren und unterschiedlich behandeln zu können, wie du später sehen wirst. Nachdem wir die Art der Nachricht geschrieben haben, können wir weitergehen und die Nachricht mit unseren gewünschten Daten füllen. In diesem Fall senden wir einen Textnachricht, die wir z.B. für eine Kommunikation von Spieler zu Spieler während des Spieles benutzen können. Wir nehmen an, das "strChatText" die Zeichenfolge enthält, die wir verschicken wollen.

Die DirectPlay4.SendEx Methode wird genutzt, um das Nachrichten-Objekt zu versenden nachdem wir es mit Informationen gefüllt haben. Das erste Parameter dieser Methode ist die "Spieler-ID" (erinnerst du dich? Wir haben sie gespeichert als wir den Spieler erstellt haben!). Das zweite, an welche(n) Spieler wir die Nachricht senden wollen. Wir können hier jeden beliebigen Spieler angeben (oder eine Gruppe... siehe SDK) oder die DPID_ALLPLAYER-Konstante benutzen, damit die Nachricht an jeden Spieler gesendet wird.

Durch das dritte Parameter legen wir die Eigenschaften fest, die wir beim Senden berücksichtigen wollen. Da gibt es ziemlich viele, inklusive DPSEND_ENCRYPT und DPSEND_SIGNED, aber meistens benutzen wir DPSEND_GUARANTEED und DPSEND_ASYNC. Benutze DPSEND_GUARANTEED wenn die Nachricht auf jeden Fall ankommen muss, DPSEND_ASYNC wenn die Nachricht nicht überlebenswichtig ist, und vielleicht durch nachfolgende Nachrichten ihre Gültigkeit verliert.

Wenn der Host z.B. ein Spiel startetn, sollten "GUARANTEED" (garantierte) Nachrichten an alle Spieler gesendet werden, weil es absolut notwendig ist, daß sie diese Information erhalten. Einmal im Spiel selbst, wird häufig viel überflüssige Information gesendet. In einem Spiel wie StarCraft (oder anderen Echtzeit-Strategiespielen) führt der Verlust einer Nachricht, die eine Truppenposition enthält, zu keinen schwerwiegenden Folgen, da die nächste Nachricht sowieso die nächst-neuere Position enthält und die erste Nachricht sowieso überholt wäre. In solchen Situationen ist es vorteilhaft Nachrichten asynchron zu senden, da sie so schneller und in einer Art "schnellfeuer Modus" gesendet werden können.

Das vierte Parameter, das die Methode DirectPlay4.SendEx enthält, muss das DirectPlayMessage - Objekt sein, das wir senden wollen. Das fünfte, sechste und siebte Parameter werden für Priorität, Zeitlimit und Kontext verwendet. Sie werden hier nicht besprochen. Das wäre einfach zu viel Stoff um es alles durchzukauen!

So, jetzt weißt du wie man eine Nachricht erstellt und sendet. Es erscheint logisch, zu lernen wie man die Nachricht empfängt und auswertet!

Dim lngFromPlayerID As Long
Dim lngToPlayerID As Long
Dim lngMsgType As Long
Dim dpMsg As DirectPlayMessage
Dim lngMsgCount As Long

    lngMsgCount = dp.GetMessageCount(lngPlayerID)

    Do While lngMsgCount > 0
        Set dpMsg = dp.Receive(lngFromPlayerID, lngToPlayerID, DPRECEIVE_ALL)
        lngMsgType = dpMsg.ReadLong()
        lngMsgCount = lngMsgCount - 1
Zuerst rufen wir die Methode DirectPlay4.GetMessageCount um die Zahl der Nachrichten zu erhalten, die eingetroffen sind und nun auf uns warten. Wir müssen die Spieler-ID an die Funktion GetMessageCount übergeben, damit DPlay weiß, für welchen Spieler wir die Nachrichten abfragen (ja, es kann mehr als ein Spieler zur gleichen Zeit aktiv sein!).

Als nächstes verarbeiten wir nacheinander alle Nachrichten. Wir erstellen ein neues DirectPlayMessage - Objekt und initiieren es mit der Methode DirectPlay4.Receive die die nächste Nachricht in der Warteschlange abruft.

Die Methode Receive gibt neben dem DirectPlayMessage zusätzlich einige andere Daten zurück. Wenn wir ihm ein paar Long-Variablen übergeben, gibt es die Spieler-ID des Senders als auch die Spieler-ID des Empfängers. Das dritte Parameter, die Flags für Empfang, geben uns die Möglichkeit, festzulegen, welche Nachrichten wir empfangen möchten. Übergeben wir die DPRECEIVE_ALL Flag, heißt das, wir wollen JEDE Nachricht empfangen. Mit anderen Konstanten können wir z.B. festlegen, daß wir nur Nachrichten von einem bestimmten Spieler empfangen möchten (z.B. der Wert des ersten Parameters) oder nur Nachrichten die zu einem bestimmten Spieler gesendet wurden (zweites Parameter).
 

Haben wir das neue Nachrichtenobjekt erhalten, können wir den ersten Long-Wert extrahieren. Dieser Wert sollte den Nachrichtentyp enthalten, wie weiter oben beschrieben. Der Wert MSG_CHATTEXT zeigt uns dann z.B. an, daß die Nachricht als Textnachricht geplant war, weil die Konstante vorher für diesen Zweck definiert wurde.
Außerdem müssen wir den Nachrichtenzähler um Eins verringern, so daß wir nur so oft Abfragen, wie auch Nachrichten zur Verarbeitung da sind.

Jetzt, da wir alle diese Informationen dieser Nachricht haben, können wir sie verarbeiten/auswerten. Als erstes müssen wir zwischen benutzerdefinierten und Systemnachrichten unterscheiden:

        If lngFromPlayerID = DPID_SYSMSG Then
        '...handle system messages...
    Else
        '...handle user-defined messages...
    End If

Die Variable "lngFromPlayerID" enthält nun die Spieler-ID des Senders der Nachricht. Dieser Wert ist gleich der Konstanten DPID_SYSMSG wenn die Nachricht NICHT benutzerdefiniert ist. Wir benutzen daher die IF Anweisung, um Systemnachrichten zu verarbeiten, und ELSE um alle anderen Werte abzudecken - also die benuterdefinierten Nachrichten.

Als nächstes Unterscheiden wir die Nachrichten nach ihrem ersten Long-Wert (der Nachrichtentyp). Eine "Select Case" Anweisung ist ideal dafür:

        Select Case lngMsgType
            Case DPSYS_DESTROYPLAYERORGROUP, DPSYS_CREATEPLAYERORGROUP
                '...a new player has joined/left the session, take action...
        End Select
Hier behandekn wir zwei Arten von möglichen Systemnachrichten. Wenn eine Spieler einem Spiel zusteigt oder es verläßt, werden diese Anweisungen ausgeführt. Wir können dann Schritte einleiten, um seine Erscheinung festzulegen (z.B. "Spielername - Ausgestiegen" o.ä. - d.Ü.)
        Select Case lngMsgType
            Case MSG_CHATTEXT
                '...we have receive chat text, take action...
                strChatText = dpMsg.ReadString()
        End Select
Hier sehen wir die Behandlung einer benutzerdefinierten Nachricht. Wenn wir erstmal wissen, daß es sich um eine Textnachricht handelt, klnnen wir die Zeichenfolge extrahieren. Diese kann in einer Zeichenfolge gespeichert werden (hier benutzen wir eine vorherdefinierte String-Variable, "strChatText") und können sie weiterverwenden.

:)

Das ist es! Was wir noch machen müssen ist DirectPlay beenden wenn wir das Programm beenden!

 (klick here um den Quellcode herunterzuladen)