XNA Multiplayer Games and Networking
- by JoshReuben
· XNA communication must by default be lightweight – if you are syncing game state between players from the Game.Update method, you must minimize traffic. That game loop may be firing 60 times a second and player 5 needs to know if his tank has collided with any player 3 and the angle of that gun turret. There are no WCF ServiceContract / DataContract niceties here, but at the same time the XNA networking stack simplifies the details. The payload must be simplistic - just an ordered set of numbers that you would map to meaningful enum values upon deserialization.
Overview
· XNA allows you to create and join multiplayer game sessions, to manage game state across clients, and to interact with the friends list
· Dependency on Gamer Services - to receive notifications such as sign-in status changes and game invitations
· two types of online multiplayer games: system link game sessions (LAN) and LIVE sessions (WAN).
· Minimum dev requirements: 1 Xbox 360 console + Creators Club membership to test network code - run 1 instance of game on Xbox 360, and 1 on a Windows-based computer
Network Sessions
· A network session is made up of players in a game + up to 8 arbitrary integer properties describing the session
· create custom enums – (e.g. GameMode, SkillLevel) as keys in NetworkSessionProperties collection
· Player state: lobby, in-play
Session Types
· local session - for split-screen gaming - requires no network traffic.
· system link session - connects multiple gaming machines over a local subnet.
· Xbox LIVE multiplayer session - occurs on the Internet. Ranked or unranked
Session Updates
· NetworkSession class Update method - must be called once per frame.
· performs the following actions:
o Sends the network packets.
o Changes the session state.
o Raises the managed events for any significant state changes.
o Returns the incoming packet data.
· synchronize the session à packet-received and state-change events à no threading issues
Session Config
· Session host - gaming machine that creates the session. XNA handles host migration
· NetworkSession properties: AllowJoinInProgress , AllowHostMigration
· NetworkSession groups: AllGamers, LocalGamers, RemoteGamers
Subscribe to NetworkSession events
· GamerJoined
· GamerLeft
· GameStarted
· GameEnded – use to return to lobby
· SessionEnded – use to return to title screen
Create a Session
session = NetworkSession.Create(
NetworkSessionType.SystemLink,
maximumLocalPlayers,
maximumGamers,
privateGamerSlots,
sessionProperties );
Start a Session
if (session.IsHost)
{
if (session.IsEveryoneReady)
{
session.StartGame();
foreach (var gamer in SignedInGamer.SignedInGamers)
{
gamer.Presence.PresenceMode =
GamerPresenceMode.InCombat;
Find a Network Session
AvailableNetworkSessionCollection availableSessions = NetworkSession.Find(
NetworkSessionType.SystemLink,
maximumLocalPlayers,
networkSessionProperties);
availableSessions.AllowJoinInProgress = true;
Join a Network Session
NetworkSession session
= NetworkSession.Join(
availableSessions[selectedSessionIndex]);
Sending Network Data
var packetWriter = new PacketWriter();
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);
}
Receiving Network 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();
…
End a Session
if (session.AllGamers.Count == 1)
{
session.EndGame();
session.Update();
}
Performance
• Aim to minimize payload, reliable in order messages
• Send Data Options:
o Unreliable, out of order -(SendDataOptions.None)
o Unreliable, in order (SendDataOptions.InOrder)
o Reliable, out of order (SendDataOptions.Reliable)
o Reliable, in order (SendDataOptions.ReliableInOrder)
o Chat data (SendDataOptions.Chat)
• Simulate: NetworkSession.SimulatedLatency , NetworkSession.SimulatedPacketLoss
• Voice support – NetworkGamer properties: HasVoice ,IsTalking , IsMutedByLocalUser