Author : Sobeit Void
Page : 1 Next >>
V 1.1 11-4-2000
by Sobeit Void
Seeing that there are few (if any) tutorials on DirectPlay, and that it is such a pain to learn DirectPlay from the MSDN (like I have), I thought I would alleviate some of the agony by writing this tutorial. Also I have this day off since I'm waiting for the monstrous 100 MB DX 7 SDK download.
If you find any errors, please email me at email@example.com
The tutorial will use Directx 5.0 or the IDirectPlay3 interface. I know DX 7.0 is out but I am still downloading it and I passed with DC 6. Although DC 5.0 is inefficient (every packet has high overhead), it seems the new versions are getting better. Anyway, the idea should mainly be the same.
The demo will be a chat program that I am using for my game. It is not a lobby server (a lobby server is something like Blizzard's BattleNet), just a client/server program. The user is assumed to be familiar with C/C++ and some Win32 programming (Of course, DX too). Some networking concepts would help. No MFC, I hate MFC. Putting another layer on Win32 API bothers me when you can access Win32 functions directly. Also, I will only use TCP/IP. If you want to use IPX, modem, or cable, check out the MSDN. They are roughly equivalent.
This tutorial by no means teaches you everything about DirectPlay. Any networking application is a pain to write, and you should consult the MDSN documentation for more information (mostly where I learnt DirectPlay from).
There is no sample demo exe too as I don't have time to write one out to show you.
What DirecPlay is About
DirectPlay is a layer above your normal network protocols (IPX, TCP/IP etc). Once the connection is made, you can send messages without needing to know what the user is connecting with. This is one of the best features (IMO) and though some of you may come up with more efficient messaging protocols with WinSock, I'd rather use DirectPlay and save me hordes of trouble. BTW, DirectPlay uses Winsock too.
Sessions in DirectPlay
A DirectPlay session is a communication channel between several computers. An application must be in a session before it can communicate with other machines. An application can either join an existing session or create a new session and wait for people to join it. Each session has one and only one host, which is the application that creates it. Only the host can change the session properties (we will get to that detail later).
The default mode in a session is peer-to-peer, meaning that the session complete state is replicated on all the machines. When one computer changes something, other computers are notified.
The other mode is client/server, which means everything is routed through a server. You manage the data in this mode, which is probably the best in a chat program. However, I used sort of a hybrid in this tutorial.
Players in DirectPlay
An application must create a player to send and receive message. Messages are always directed to a player and not the computer. At this point, your application should not even know about the computer's location. Every message you sent is directed at a specific player and every received message is directed at a specific local player (except for system messages; more on that later). Players are identified only as local (exist on your computer) or remote (exist on another computer). Though you can create more than one local player on your machine, I find it not very useful. DirectPlay offers additional methods to store application specific data so you don't have to implement a list of players but I'd rather do my own list.
You can also group players in the same session together so any message sent to you will get directed to the group. This is great for games where you can ally with other people and you want to send messages to your allies only. Unfortunately, you have to explore that area on your own.
If at this point you find all this very troublesome, try writing your own network API. You will be glad what DirectPlay does for you.
Messages in DirectPlay
Now we have a session and a player, we can start sending messages. As I said, each message sent is marked by a specific local player and can be sent to any player. Each message received is placed in a queue for that local player. Since I create only one player, all the messages belong to that player. You don't need to bother about this queue; all you need is to extract the messages from it and act on them. The application can poll the receive queue for messages or use a separate thread and events. I tried the thread method and it works great, except for when I use MessageBox to notify the user (in case you don't know, MessageBox displays a message box in Windows). If you want to use threads, you need to pause the thread when the application displays a message box and somehow it gets very messy with synchronization. So I opted for the poll method. Feel free to use threads if you think you can handle it.
There are two types of messages: player and system. Player messages have a sender and receiver. System messages are sent to every player and are marked sent from the system (DPID_SYSMSG). DP stands for DirectPlay, ID for identification. If you cannot understand messages, go and learn more about DirectDraw first. System messages are generated when the session state is changed, i.e. when a new player joins the session.
Note: There are also security features using the Security Support Provider Interface (SSPI) on windows. These messages are encrypted and such. I don't think this is of much use in gaming.
Whew. Now we get to more details. If you didn't quite understand any of the above, please read them again till you do. If you have any questions like "What if..." it will be answered soon. So let's move on.
The first thing to do is to include the DirectPlay header files:
#include // directplay main
#include // the directplay lobby
Also add DPLAYX.LIB to your project.
If you are wondering why there is a dplay.lib and dplayx.lib, add the dplayx.lib cause I think there are more methods there used in the lobby. Also if you are asking why am I including the dplobby methods when I am not using a lobby server, it will become clearer later.
Also you need to define INITGUID or add the dxguid.lib. Define this at the very top of your project.
#define INITGUID // to use the predefined ids
Next you need to give you application a GUID (Global Unique Id). This ID is to distinguish the application in the computer. You don't want your application to send messages to your browser, only your application. You can use guidgen.exe to create a id for your application. Microsoft guarantees that it will never mathematically create the same GUID twice, so we take their word for it. It will look something like
0x5bfdb060, 0x6a4, 0x11d0, 0x9c, 0x4f, 0x0, 0xa0, 0xc9, 0x5, 0x42, 0x5e);
Now to define our globals
LPDIRECTPLAY3A lpdp = NULL; // interface pointer to directplay
LPDIRECTPLAYLOBBY2A lpdplobby = NULL; // lobby interface pointer
If you are wondering what the A behind the interface stands for, it means ANSI version. There are two versions for DirectPlay – ANSI and Unicode. (Unicode is a standard for using 16 bits to represent a character instead of 8 bits, just for internationalization. Just use the ANSI version and forget about supporting multiple languages. Makes everybody happy.)
The next thing is the main loop of the program. This is the bare skeleton of what it looks like.
// Get information from local player
// Initialize Directplay connection from the information from above
// Your normal translating message
} // end if PeekMessage(..)
// Your game loop
// Receive messages – We will implement this
} // end else
} // end of while(1)
// Close Directplay Connection
How you get information from the user is up to you. You can do it via a dialog box or any other way you deem. The main thing you need to get is the name and whether if it is the server or client. If it is the server, you get the session name. If it is the client, you get the TCP/IP address
Page : 1 Next >>