XNA Multiplayer Games and Networking

·        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