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("224.109.108.107"), 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: http://www.microsoft.com/downloads/en/details.aspx?FamilyID=77586864-ab15-40e1-bc38-713a95a56a05&displaylang=en

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

Ricky

WindowsPhonePlatformer.zip


Comments (38)

  1. Steve Williams says:

    Where did 224.0.1.100 come from for the IPAddress?

  2. RickyTTan says:

    224.0.1.100 is a multicast address.  Multicast addresses are in the range of 224.0.0.0 to 239.255.255.255 (en.wikipedia.org/…/Multicast_address).

  3. That's my other Live ID above.

    After some reading, that address falls in the IANA-governed Internetwork Control Block.  That particular address is currently assigned to NASDAQ.  The IANA also states that addresses in this range should not be used unless assigned.

    So, what are the rules on choosing an address to use?  Was that address picked at random?

  4. Ricky_T says:

    Thanks for pointing that out.  That address was picked at random.  I've changed it to one that is not in the reserved list, 224.109.108.107.

  5. george says:

    Friends dont miss it please

    esp. USA,UK and German friends

    http://adf.ly/1q5di

  6. Redtalon says:

    Hi, tried implementing this into a new game I am working on to see if I could get it to work outside the demo.

    I am running it on my phone and in the emulator to represent two seperate devices, this works on your demo.

    The problem I am having is that one of them freezes at random, doesn't matter if I am running it or selecting from the phone menu.

    Any ideas? I know its difficult to say without seeing the code. I have tried using "lock" (around the variables) in the event raised for receiving data but still dont know what is causing it.

    Cheers

    Red

  7. Karl Shifflett says:

    Does this only work with XNA or can Silverlight games take advantage of this?

    Many thanks,

    Karl

  8. Ricky_T says:

    @Redtalon:  This is a known issue, and should be fixed for the final release.

    @Karl:  The Socket APIs are from Silverlight.  So Silverlight games can definitely take advantage of this.

  9. Karl Shifflett says:

    Rick,

    Thank you for confirming.

    Best,

    Karl

  10. Hello, interesting code indeed. I am trying to reuse this code for a windows phone application. Packets are correctly received but when I try to update a textblock from the message of the PacketReceived event I get a "Invalid cross-thread access."

    Any idea?

    Thanks in advance

  11. Ricky_T says:

    The PacketReceived event comes in on a background thread.  To access the UI thread from a background thread, you can use the Dispatcher:

    this.Dispatcher.BeginInvoke(() => textBlock1.Text = text);

  12. RedTalon says:

    Are there any plans for Sockets support on the XBOX 360, where players can join in with their phones?

  13. Ricky_T says:

    That would be really cool.  I don't know about plans for XBOX 360.  You could check on the XBOX 360 forums.

  14. RedTalon says:

    I think the ability to play an XBOX game and have a WP7 friend jump in would be crazily addictive.

    I will ask about.

  15. Hello says:

    Would I use this code if I wanted a game where a user could choose to join up with a specific phone, whether or not that phone is on the same WiFi? For example, a two-player tic-tac-toe where users choose their opponents from a list of friends, or another random phone.

  16. Hello says:

    Would I use this code if I wanted a game where a user could choose to join up with a specific phone, whether or not that phone is on the same WiFi? For example, a two-player tic-tac-toe where users choose their opponents from a list of friends, or another random phone.

  17. Ricky_T says:

    Multicast is limited to the same network only.  For your scenario, you could use TCP sockets.  Earlier this year in MIX 2011, there was a demo of a simple IRC client that does this scenario where your phone could talk to random people on the IRC channel.

  18. Tishawn Fahie says:

    Ricky_T thankyou very much for this… I'm trying to create a simple test with a texture2d player and Vector2 positions test on Emulater and Phone running mango.. No such luck.. Anyway you can create a quick source code just for us people who isnt so great in programming?

  19. Tishawn Fahie says:

    Another question is would it be possible to have say Mango Phone control a character using sockets to a Windows Xna game??

  20. Ricky_T says:

    Hi Tishawn,

    I'm using Texture2D and Vector2 in this sample.  You can download the source code which is attached to this blog.

    Yes, it's possible.  Your Windows XNA game needs to have a socket open for listening.  Then have your Mango Phone control the character and send the information to the Windows XNA game via the socket.

    Regards,

    Ricky

  21. Tishawn Fahie says:

    Thank you very much Ricky_T I was able to get this to work with no problems!! One more questions.. I usually dont ask for help without trying everything.. I think I have… I am now trying to shoot an projectile at the second player… Now I'm trying to make it so that that projectile will show on the emulator as it trying to hit the second player.. No such luck.. I tried everthing from a bullet class draw methods etc….Would you be able to guide me on where to start???  I can see the projectile hitting 2nd player on my phone but on the emulator there's no projectile showing at all… Any suggestions??

  22. mercator says:

    Hi, is there any way to do a Peer-to-Peer Multiplayer Game with ad-hoc wifi or bluetooth?

  23. Ricky_T says:

    @Tishawn:  You could use a sprite to draw the projectile using a png image, similar to drawing a player sprite.

    @mercator:  At this time, I don't think there's a way to do this with ad-hoc wifi or bluetooth.

  24. Steve says:

    Is there a way to implement this in a simple game of pong? my code all takes place in one class and the example uses 3 (OtherPlayer, level, and PlatformerGame)

  25. Ricky_T says:

    Yes, you can implement this in a simple game of pong, with your code in one class.  You can follow the sample code in PlatformerGame.cs.

  26. Steve says:

    Thanks for the lighting fast response but i've been working on this i few days now and i can't get it to work. I was wondering:

    1).  Do I need to create a class for OtherPlayer

    2). If not should all the references in the sample code for OtherPlayer simply changed to the name i am using for my paddle's Vector2 position?

    3). since everything is in the same class do i still need to call Dictionary?

  27. Ricky_T says:

    What issue are you seeing?  It might be easier for you to create a new project, and follow the code in UdpAnySourceMulticastChannel to get simple Send and Receive working.  Then put the code into your app to update the paddle's position on Receive.

    1. No.  I just found it easier to different the local player vs the other player.

    2. Yes, change the logic to update your paddle's Vector2 position.

    3. No, Dictionary is just a data structure used to store key value pairs.

  28. Steve says:

    Thanks again i was also wondering if i should put the logic for controlling the paddle inside the Channel_PacketReceived method?

    the project deploys and running properly but there is no interaction from the other device

  29. Ricky_T says:

    You're welcome. Yes, you should put that logic in the Channel_PacketReceived method.

  30. Mike says:

    hey thanks for the example, you rock! one question how would i go about starting the players at different positions

  31. (jun) rcortesjr.blogspot.com says:

    Hi, I admire your work ! Looks very simple but effective but I need to ask this lines of codes:

                   this.Client.BeginSendTo(data, 0, data.Length,endPoint,

                       result =>

                       {

                           this.Client.EndSendToGroup(result);

                       }, null);

    I wonder if your code should be like Client.EndSendTo()  not Client.EndSendToGroup() ?

  32. Ricky_T says:

    @Mike:  You can change the starting positions in the txt file at WindowsPhonePlatformerContentLevels.

    @jun:  In this case, we want to send the same data to all players in the group, so we use EndSendToGroup().  If we wanted to send a private message to a specific player, then we can use EndSendTo().

  33. Alaa Eltayeb says:

    Do the players have to be on the same network to play ??

  34. Ricky_T says:

    Yes, players need to be on the same WiFi network to play.

    To play across different networks, you'll need to set up a TCP or UDP server, and have the different players connect to the server.  

  35. Alaa Eltayeb says:

    Do you have a tutorial or sample on how to do that??

  36. Rohan says:

    Hi Ricky, and congrats on getting published =) I would like to use your project to make my own multiplayer app on Windows Phone, but when I extract the archive, I get the following error:

    !   D:DownloadsWindowsPhonePlatformer (1).zip: The archive is corrupt

    !   D:DownloadsWindowsPhonePlatformer (1).zip: The archive is corrupt

    !   D:DownloadsWindowsPhonePlatformer (1).zip: CRC failed in WindowsPhonePlatformerWindowsPhonePlatformerContentSoundsExitReached.wma. The file is corrupt

    !   D:DownloadsWindowsPhonePlatformer (1).zip: The archive is corrupt

  37. Ricky_T says:

    Thanks.  I'm not sure what happened to the zip package that caused it to stop working.  I've re-uploaded the zip file.

Skip to main content