Windows Phone Peer-to-Peer Multiplayer Game using Sockets in XNA

One of the new features for the app platform in Windows Phone Mango is TCP and UDP Sockets.  In this blog post, I'll talk about using this to augment an existing game to add peer-to-peer multiplayer over WiFi using UdpAnySourceMulticastClient.  Phones running the game on the same WiFi network automatically discover one another and the players just appear on the screen.

The game itself is from another sample, the Windows Phone 7 Platformer Starter Kit from David Rousset's blog.

The changes are to add code to run UDP Multicast sockets and to enable multiplayer. 

The source code for the full project is attached in the zip file below.

PlatformerGame.cs:  This contains the game code and is where the sockets are initialized, and where the sends and receives are handled. 

UdpAnySourceMulticastChannel.cs: This contains the UDP multicast sockets code for joining the group, sending and receiving data.

OtherPlayer.cs:  This is a modification of Player.cs to add other players to the game.

Sockets Initialization in PlatformerGame.cs:

 private void InitializeSockets() { this.Channel = new UdpAnySourceMulticastChannel(IPAddress.Parse(""), 3007); this.Channel.PacketReceived += new EventHandler<UdpPacketReceivedEventArgs>(Channel_PacketReceived); this.Channel.Open(); } 


This joins the UdpAnySourceMulticastClient group and sets it up to receive data: 



  public void Open() { if (!IsJoined) { this.Client.BeginJoinGroup( result => { try { this.Client.EndJoinGroup(result); IsJoined = true; this.OnAfterOpen(); this.Receive(); } catch { } }, null); } } private void Receive() { if (IsJoined) { Array.Clear(this.ReceiveBuffer, 0, this.ReceiveBuffer.Length); this.Client.BeginReceiveFromGroup(this.ReceiveBuffer, 0, this.ReceiveBuffer.Length, result => { if (!IsDisposed) { IPEndPoint source; try { this.Client.EndReceiveFromGroup(result, out source); this.OnReceive(source, this.ReceiveBuffer); this.Receive(); } catch { IsJoined = false; this.Open(); } } }, null); } }


Each time a player moves, it sends its new position and velocity to the multicast group.


  private void SendPosition(string position) { if (level.Player.Position.X != oldPosition.X || level.Player.Position.Y != oldPosition.Y) { oldPosition = level.Player.Position; this.Channel.Send(position); } }


This sends the packet to the multicast group.


  public void Send(string format, params object[] args) { if (IsJoined) { byte[] data = Encoding.UTF8.GetBytes(string.Format(format, args)); this.Client.BeginSendToGroup(data, 0, data.Length, result => { this.Client.EndSendToGroup(result); }, null); } }


When a packet gets received, the receive handler updates the other player so that it looks like the other player is moving. Each phone in the multicast group receives this and updates accordingly.


  void Channel_PacketReceived(object sender, UdpPacketReceivedEventArgs e) { string data = e.Message; Console.WriteLine(data); string[] pos = data.Split(','); //Discard packets that do not match if (pos.Length != 5) { return; } try { if (pos[0] != identifier.ToString()) //if not originated from this phone { if (pos[1].Contains("ReachedExit")) { level.TimeRemaining = TimeSpan.Zero; } else { Vector2 position = new Vector2(float.Parse(pos[1]), float.Parse(pos[2])); Vector2 velocity = new Vector2(float.Parse(pos[3]), float.Parse(pos[4])); level.UpdateOtherPlayer(int.Parse(pos[0]), position, velocity); } } } catch (Exception ex) { System.Diagnostics.Debug.WriteLine("Caught unexpected exception: " + ex.Message); } }


To play, use the accelerometer to move left or right. Tap on the screen to jump. Multiplayer requires WiFi network.



To get the Windows Phone Mango Developer Tools Beta:

Hope this helps show a simple way to communicate from phone to phone and demonstrate the power of sockets.  Happy developing!