Types Of Network Games

When creating a networked game, there are two major paradigms -- client/sever versus peer-to-peer

Client-Server

In the client/server model, one machine works as a server that controls the gameplay, while other machines are clients, that only make change to the global state by making requests to the server. The server may be a "dedicated server" -- that is, a machine that no person is playing on, or one of the player's machines may act as a server. Massively Multiplayer Online games like World of Warcraft are all Client/server games, the Onlive service is a rather extreme version of a client-server model (where the clients are essentially sending keypresses down the wire, and getting video back)

Peer-to-Peer

In the Peer-to-peer model, there is no official server that all clients connect to -- instead each client does some calculation, and receives results from other machines. A two-person chat room (I send you messages, you send me messages) is a simple "pure" peer-to-peer network (once the connection has been made)

Combination Models

Most games that do not have a central server (which includes almost all xbox game) are a mix of client/server and peer-to-peer. One of the machines is specified as the server, and other machines connect to it. Some computation is done on each machine, but some central abritration is done by the server machine. Some care should be taken to ensure that the player playing on the server machine does not have an advantage over players on the client machines

Using XNA networking

XNA Networked games have the following flow (with some caveats below):

Network Overview

Housekeeping details: Before you start

There are a few bits of code that you will need to include before you can start using the networking framework. First of all, you need to add a GamerServices component. Your constructor will need something like:

              Components.Add(new GamerServicesComponent(this));
  

Also, before you can create a server (or search for one), a gamertag needs to be signed into the current machine (for both PC and xbox). Your update method should have something like the following at the beginning:

            if (IsActive && Gamer.SignedInGamers.Count == 0)
            {
                // If there are no profiles signed in, we cannot proceed.
                // Show the Guide so the user can sign in.
                Guide.ShowSignIn(1, false);
            }
  

Note that you will definitely need to call the superclass update method in your update method (so that the GamerServices component will get update calls, which allows it to be functional

Creating a Network object

Creating a network object to host a game is easy, using the XNA networking library:

public static NetworkSession Create(NetworkSessionType sessionType, int maxLocalGamers, int maxGamers);

So, to create a network session for a simple game with one local player and one networked player, we could do something like:

networkSession = NetworkSession.Create(NetworkSessionType.SystemLink, 1, 2);

Once we have created a network session, we can hook up callbacks, so we can handle various network events:

All we need to do now is wait for our clients to connect, and signal that they are ready. Note that we also need to handle signalling when we are ready, and we will need to update the network session every frame so that it can do its work

Connecting clients

To connect to a host, we first find all available hosts, select one, and then connect to it.

 AvailableNetworkSessionCollection availableSessions =
         NetworkSession.Find(NetworkSessionType.SystemLink, 1, null)
 
 // Connecting to first session we find:
 
  networkSession = NetworkSession.Join(availableSessions[0])

Of course, instead of connecting to the first one we find, we could instead take a look at various properties of each session, to find the one we want to join. When we join a game, we will also need to hook up network events, so that we can be notified of various network changes

Leaving the Lobby -- Starting the Game

Each player can say that she/he is ready by setting the IsReady property on the network session:

 foreach (LocalNetworkGamer g in networkSession.LocalGamers)
 {
     g.IsReady = true;
  }

The host can check if everyone is ready, and start the game

if (networkSession.IsEveryoneReady && networkSession.IsHost)
{
       networkSession.StartGame();
}

Once the game is started, then the GameStarted event is sent, the game is no longer considered availble, and the game can begin

Sending Data

To send data, first create a packet reader and packet writer, used to read an write packets. This can be done once, creating global (or local to your networking class) instance variables

        PacketWriter packetWriter = new PacketWriter();
        PacketReader packetReader = new PacketReader();
  

Once you have your packet writer, you can send data by first writing to the packet writer, and then sending the data off. For instance, if we were just sending a single Vector2, the position of our paddle for a networked pong game, we could do something like:

  
            packetWriter.Write(mWorld.mMyPaddle.mObjectSprite.Position);
            networkSession.LocalGamers[0].SendData(packetWriter, SendDataOptions.InOrder);

To data, we can first see if there are any packets available, and then process it:

  LocalNetworkGamer gamer = networkSession.LocalGamers[0];
  while (gamer.IsDataAvailable)
  {
      NetworkGamer sender;

      // Read a single packet from the network.
      gamer.ReceiveData(packetReader, out sender);

      // Discard packets sent by local gamers
      if (sender.IsLocal)
            continue;
            
      // Read in any data
      //   WARNING:  be sure that your data sent matches the data received!
      Vector2 opponentPosition = packetReader.ReadVector2();

      // Use the network data to update your current game state

      mWorld.mOpponentPaddle.mObjectSprite.Position = opponentPosition;
  

Example: Pong

Download the following .zip file, which contains necessary project files.

NetworkPong.zip

Note that there are 3 solutions: A windows solution, an xbox solution, and a combo solution. Open both the windows and xbox solutions. Run both of them simultaneously to test your code. If you are making changes to a file, you only need to make changes in one solution (since the files are all shared). If you add a file to a project in a solution, you need to add it to the other solution as well (by using "add existing ...", or by adding the file using the combo solution).

Once you have everything running on the windows and 360 boxes, make the following changes: