160 likes | 594 Views
Network Games in XNA http://msdn2.microsoft.com/en-us/library/bb975801.aspx Soon Tee Teoh CS134 Getting Started With Networked Games XNA Framework games must explicitly initalize the gamer services subsystem before networking API calls can be completed.
E N D
Network Games in XNAhttp://msdn2.microsoft.com/en-us/library/bb975801.aspx Soon Tee Teoh CS134
Getting Started With Networked Games • XNA Framework games must explicitly initalize the gamer services subsystem before networking API calls can be completed. • Most games will use the GamerServicesComponent, a game component which takes care of the process of initializing and pumping the gamer services system. • This component will automatically pass through the graphics device and window handle and call GamerServicesDispatcher.Update to pump the gamer services pump at regular intervals. • To take advantage of this component, most games will simply need to add one line to the Game constructor: Components.Add(new GamerServicesComponent(this));
Hardware Requirements • It is not possible to run multiple simultaneous instances of a networked game on a single development computer. • When launching to multiple machines for network testing, we recommend that you load multiple copies of your solution into separate Visual Studio instances, one per machine.
Network Session Management • The NetworkSession class has a single Update method that must be called once per frame. This performs the following actions: • Sends network packets. • Changes session state such as which players are in the session and who is currently talking. • Raises managed events for any significant state changes. • Returns incoming packet data. • This explicit update call allows the framework to synchronize the session so that packet received and state change events will never be raised asynchronously with the rest of the game code. This allows developers to program against the network session object without any threading concerns. • Session updates are kept separate from the gamer services system pumping for two reasons: • To clarify when session events will be raised. • To allow developers the option to update the session from a background worker thread, allowing these developers the option to run this in parallel with the main game update.
Matchmaking • To play a networked game with other people, the game needs a way to publish an instance of the game for others to discover the instance and join the game. • This matchmaking and peer discovery mechanism is available through the NetworkSession.Find and NetworkSession.BeginFind methods, which return a collection of AvailableNetworkSession instances. • You may examine the properties of each AvailableNetworkSession and pass a suitable AvailableNetworkSession to Join to join the session. public static AvailableNetworkSessionCollection Find ( NetworkSessionType sessionType, int maxLocalGamers, NetworkSessionProperties searchProperties ); AvailableNetworkSessionCollection availableSessions; int maximumLocalPlayers = 1; availableSessions = NetworkSession.Find( NetworkSessionType.SystemLink, maximumLocalPlayers, searchProperties);
Players • The NetworkSession object exposes a collection of player instances, along with events indicating when players join or leave the session. • There are properties for querying which player is the host (NetworkSession.Host) and for determining which players are local players signed on to the same machine and physically located together (NetworkGamer.IsLocal).
Players Joining and Leaving • A NetworkSession contains several properties which list of the players who have joined a session. The collection of all gamers in a session is described by the property NetworkSession.AllGamers, and is guaranteed to be the same on all game machines in a session. Within this list, the gamers might be local (playing on the same game machine through split-screen play) or remote (playing on a different game machine). The list of all local players playing from a local game machine is described by the property NetworkSession.LocalGamers. The list of all players not playing on the local game machine is contained in the NetworkSession.RemoteGamers property. • To respond to players joining or leaving the game, you may subscribe to the NetworkSession.GamerJoined and NetworkSession.GamerLeft events with and create custom event handlers.
Local Sign-In • When first creating a session, a game must specify the maxium number of local players that it supports (1, 2, 3, or 4). • The framework will automatically add up to this number of profiles to the session, and keep this up-to-date if the sign-in state changes. • If there are more signed-in profiles than the game wants, only the lower-numbered profiles will be added to the session. • If extra players sign after the session is created the players will not be added. • If the host player signs off, the session will either be torn down or a host migration will take place depending on whether the NetworkSession.AllowHostMigration option is enabled.
Create a Network Session • There are multiple types of sessions that can be created, such as • a local session (used for split-screen gaming and requiring no network traffic), • system link sessions (which connect multiple gaming machines over a local subnet), or • Xbox LIVE matchmaking sessions, which take place over the Internet. • The gaming machine which creates the session is called the host, and owns the multiplayer session. • The host does not imply a game server or authority. There are no network topologies implied, such as client-server, peer-to-peer, or hybrid. • The network topology will be determined by your implementation of your game.
Create a Network Session NetworkSession session; int maximumGamers = 8; // The maximum supported is 31 int privateGamerSlots = 2; int maximumLocalPlayers = 1; // Create the session session = NetworkSession.Create( NetworkSessionType.SystemLink, maximumLocalPlayers, maximumGamers, privateGamerSlots, sessionProperties );
To Subscribe to Session Events • Subscribe to any session events that your game is interested in. Multiplayer sessions have events that occur when the game transitions from lobby to gameplay (GameStarted and GameEnded), when players join and leave (GamerJoined and GamerLeft), when the host changes (HostChanged), and when the session ends (SessionEnded). session.GamerJoined += new EventHandler<GamerJoinedEventArgs>(session_GamerJoined); session.GamerLeft += new EventHandler<GamerLeftEventArgs>(session_GamerLeft); Programmer defined function
Send data to all peers • Create a PacketWriter to use in writing the data. The PacketWriter is a helper for efficiently formatting outgoing network packets. A multiplayer game can create a single PacketWriter instance at startup, and reuse it any time they want to send a packet. • Each LocalNetworkGamer playing on the same game machine might send data, so here we loop through the LocalGamers collection. To send a packet, call the various overloads of the PacketWriter.Write method to store data into the writer, and then pass the PacketWriter to SendData. Note that it is also possible to send data to a specific player by specifying the player in the call to SendData. • Sending the packet will automatically clear the PacketWriter, so it can then be reused to write different data for another packet. Although it is not used in this example, the PacketWriter supports offsets through the Position property. • In the call to SendData, be careful to specify a SendDataOptions value for options that is appropriate for the type of data being sent. Not all game data needs to be sent reliably, and sending excessive data using SendDataOptions.ReliableInOrder can cause the client to lag as it waits for data to be delivered in order.
Send data to all peers foreach (LocalNetworkGamer gamer in session.LocalGamers) { // Get the tank associated with this player. Tank myTank = gamer.Tag as Tank; // Write the data. packetWriter.Write(myTank.Position); packetWriter.Write(myTank.TankRotation); packetWriter.Write(myTank.TurretRotation); packetWriter.Write(myTank.IsFiring); packetWriter.Write(myTank.Health); // Send it to everyone. gamer.SendData(packetWriter, SendDataOptions.None); }
How to receive data • Create a PacketReader to assist in reading the incoming network data. A PacketReader is a helper for efficiently reading incoming network packets. A multiplayer game can create a single PacketReader instance at startup, and reuse it any time they want to read a packet. • Each LocalNetworkGamer playing on the same game machine might receive data, so here we loop through the LocalGamers collection. To read a packet, pass the PacketReader to ReceiveData, then use the various PacketReader.Read methods to extract data from the reader.
How to receive data foreach (LocalNetworkGamer gamer in session.LocalGamers) { // Keep reading while packets are available. while (gamer.IsDataAvailable) { NetworkGamer sender; // Read a single packet. gamer.ReceiveData(packetReader, out sender); if (!sender.IsLocal) { // Get the tank associated with this packet. Tank remoteTank = sender.Tag as Tank; // Read the data and apply it to the tank. remoteTank.Position = packetReader.ReadVector2(); remoteTank.TankRotation = packetReader.ReadSingle(); remoteTank.TurretRotation = packetReader.ReadSingle(); remoteTank.IsFiring = packetReader.ReadBoolean(); remoteTank.Health = packetReader.ReadInt32(); } } }
To End the Session • If you are a host ending the session purposefully and the conditions for ending the session have been met, call NetworkSession.EndGame. • In this example, when the host presses the ESC key or Back button indicating that the player wishes to exit the game, the host checks if there are players remaining in the game before ending the session. // Check for exit. if (gamePad.Buttons.Back == ButtonState.Pressed) { if (session.AllGamers.Count == 1) { session.EndGame(); } else { Exit(); } session.Dispose(); session = null; }