Main Site Links Resources Tutorials
News VB Gaming Code Downloads DirectX 7
Contact Webmaster VB Programming Product Reviews DirectX 8
  General Multimedia Articles DirectX 9

DirectPlay: Messaging
By: Jack Hoxley
Written: July 2000

You will need to have read the tutorial on DirectPlay Basics before attempting any of this.

This is where it gets interesting. In theory the whole idea behind DirectPlay is to send information (in the form of messages) between two computers. There are two types of messages used in DirectPlay - System messages (Automatic) and User-Defined messages (Incurred by the player doing something). A typical system message will be something along the lines of "XX Player has joined" or "Game has terminated" (In less useful words). A typical User-Defined message can be a chat message (which the user sees) or an update packet - sent by the program; for example, telling player X that player Y has moved - and to update it on their screen.

When sending packets around keep them small. It should be fairly obvious that sending large packets will slow things down (as the end-player has to effectively download them). A high latency (Ping/Lag) is what is incurred when sending lots of data - any online player will tell you that a high latency is bad. There are three main things you need to bare in mind when sending packets:

  1. Compression. This would require testing, but if you need to send lots of data around try compressing it first - bare in mind that the player at the other end will need to de-compress it before it can be used.
  2. Time Slicing. A lot of people ignore this - but it will speed your game up dramatically. Most people make the mistake of sending a packet on every cycle of the loop - if there is a high latency you will only increase it this way. Time slicing involves sending the data on every 2nd loop 3rd, 4th loop etc.. This way is fine for a fairly fast machine, but if it is a slower machine then it will grind to a halt effectively. So, you could also try sending data every 100ms - 10x a second; or less. You could even let the user choose - he/she will know how good their connection is, and may well want to sacrifice smooth movement for slightly faster gameplay.
  3. Minimal Data. Dont include anything in the packet that isn't required - If you are sending a new X,Y,Z coordinate for the player - DO NOT send it like "X=90 Y=12 Z =0.1" (15 bytes); the same could be sent as "90|12|0.1" (9 bytes); thats 6 less bytes you have to send, preferably, send it in binary. Assuming XYZ are all single's then to send any value for them it would be 12 bytes (even if in string form it's 100 characters long). It may seem like peanuts to you now, but it can make a big difference in the actual game...

So, I want to send a message now.
There are (obviously) two parts to sending a message - the source sending it and the destination receiving it. First we'll learn how to compile a message. There is a built in data type for this; "DirectPlayMessage", basically, we fill this with valid information and then send this data.

'We define ourselves some constants to hold the message type - this is important because when
'the destination wants to unpack the data it can use this value to work out what it should be looking for.

const MyGame_ChatMessage = 0
const MyGame_DataPacket = 1
const MyGame_SomeOtherType = 2
const MyGame_YetAnotherMessageType = 3
'This object holds everything that we need to send.
Dim Msg As DirectPlayMessage

'Use DirectPlay to initialise our message object.
Set Msg = Dp.CreateMessage
Msg.WriteLong MyGame_ChatMessage 'The message will hold an identifier
Msg.WriteString "Hello. I am a chat string." 'Stick the string data here
'There are several different data types you can write into the message; and you can use more than one:
'WriteSingle = Any valid single data type (ie. Decimal number)
'WriteDouble = Any valid Double data type (Same as a single, but bigger)
'WriteShort = Any valid Integer data type
'WriteLong = Any valid Long data type (Same as integer, but bigger)
'WriteGUID = Writes a string to the message - Almost identical to the WriteString method
'WriteString = Write any string to the message, this can be used to send data packets
'WriteByte = Writes a byte to the message

'Now that we've compiled our message into a single structure; we can send it to a single player,
' or lots of players.


'There are lots of flags to go in here. The first flag MUST be the player ID of a player on the loal computer.
'This value should be the value returned when you created a player. The second flag is who it is going to
'Get the message; you can use the constant DPID_ALLPLAYERS otherwise specify a player number
'which corresponds with the number they got when they created their player. The third flag describes
'How it should be sent. The flags that can be used are listed below:
'DPSEND_ASYNC = The program keeps on going straight away; and does not pause until the message is sent
'DPSEND_ENCRYPTED = Encrypts the message; only available in a secure session (game)
'DPSEND_GUARANTEED = If possible; the message is garaunteed to get there
'DPSEND_NOSENDCOMPLETEMSG = This can only go in if ASYNC is posted as well.
'DPSEND_SIGNED = Where possible use a digital signiture. It can only go with the GUARANTEED flag.
'The fourth flag defines the priority level of the message; not every server/connection will support this option;
' so be wary of DPERR_UNSUPPORTED being generated. It is on a scale of 0-65536 and it will only
' be sent when there are no messages with higher priority waiting.
'The fifth flag is the timeout in Ms, again, not all servers support this option. If the message can not be sent within the
'specified time limit it is cancelled. This is useful if a message is only valid for a short amount of time. Setting to 0 means
'No time limit.
'The last parameter can be ignored most of the time; it forces DP to append this value to the message ID.

Okay. Now you should be able to send a message to another player. You need to decide what type of message flags you need to use; otherwise it may well affect your gameplay. For example, Only Chat messages really need to be sent GUARANTEED as you want to make sure that it gets to the destination. An update packet (ie. Unit XX has moved) doesn't need to be sent GUARANTEED; it can be sent ASYNC instead. This is because the unit is quite likely to move again (and send another message) so the previous message may well be out of date or replaced very quickly.

Now I've sent something; I want to recieve something.
There is no point in sending a message If you cant recieve it - fairly obvious really. You will need to modify this code to suit your message needs - once you've recieved the data from DirectPlay it's up to you to do something to it. Note; you must take out the data in the same order that you packed it.

'We need a few variables to hold stuff....
Dim FromThisPlayer as long, ToThisPlayer as long, NumMessagesWaiting as long, MsgType as Long
Dim Msg as DirectPlayMessage

NumMessagesWaiting = Dp.GetMessageCount(PlayerID) 'check the messages for our Player ONLY

Do While NumMessagesWaiting >0
Set Msg = Dp.Recieve(FromThisPlayer, ToThisPlayer, DPRECIEVE_ALL)
'The variables FromThisPlayer and ToThisPlayer have the ID numbers of their respective players.
'DPRECIEVE_ALL basically means that we look at all the messages. We can now unpack the data

MsgType = Msg.ReadLong()
'Now we process the message - we'll do this in another procedure...
ProcessMessage MsgType, FromThisPlayer

'Now we decrement the number of messages waiting - to clear the message we just read.
NumMessagesWaiting = NumMessagesWaiting -1

Sub ProcessMessage(Type as Long, From as Long)
If From = DPID_SYSMSG then
'We have a message from the DirectPlay system. There are a lot of System Messages; the most important ones
'DPSYS _CREATEPLAYERORGROUP - A new player or group have joined
'DPSYS _DESTROYPLAYERORGROUP - An existing player has left
'DPSYS_HOST - The current host has left the game; the application that recieves this is now the new host.
'DPSYS _SESSIONLOST - The connection with the session has been lost.

'We Have a message of custom-Type. The best method is to use a Select Case:
Select Case Type
Case MyGame_ChatMessage
'Execute code that unpacks and displays a chat message
Case MyGame_DataPacket
'Do Code that unpacks a data packet, and acts on it.
End Select 'Just keep on adding Case's for the constants defined earlier.
End If
End Sub

You should now be able to read and write messages for your applications. This is a rather large part of DirectPlay - so now it is all down hill from here; you've done the hard stuff....

DirectX 4 VB 2000 Jack Hoxley. All rights reserved.
Reproduction of this site and it's contents, in whole or in part, is prohibited,
except where explicitly stated otherwise.
Design by Mateo
Contact Webmaster