THE OFFICIAL WEBSITE OF INDIGO ENTERTAINMENT
Flash P2P  
10/24/2011
Posted by Earl Andre Vergara
Posted in Tutorials

This tutorial will teach you how to connect two or more swf movies, air applications, iOS and Android apps built with Actionscript 3.  It basically allows your movies to send and receive data amongst themselves, or allow them to control one another.   Please note however that though P2P is available regardless of network, this tutorial focuses more on applications on the same local network.

A lot of neat applications can come out of this; one example is you can rig your online games to connect to an iOS or Android device, where the connected device would act as the controller enabling you to play the game even while away from the keyboard and mouse.  Another could have you controlling a desktop Flash presentation/slide show with a connected device.

Above are two swfs connected via P2P for demonstration purposes.
(Please allow P2P on Flash Player dialog box if asked)
Click and drag on the RED circle.

In the above example, the swf with the red circle is the controller while the one with the blue circle is the receiver.  But your swfs can be both controllers and receivers at the same time.  Also, if you download both swf, you can open many instances of the swf with the blue circle and the controller will be able to control all of them at the same time.
 
Now let's start building your application.  The first thing to do is to import the classes to be used.  P2P requires a NetConnection to act as a bridge between your applications or movies, and a NetGroup so your apps only listens to specific traffic in cases where there is more than one active connection.

// import required classes
import flash.events.NetStatusEvent;
import flash.net.NetConnection;
import flash.net.NetGroup;
import flash.net.GroupSpecifier;
import flash.events.MouseEvent;
 
var nc:NetConnection;
var group:NetGroup;
var obj:Object = {};

After creating our variables, we can now attempt to create a new NetConnection object and connect to via Real Time Media Flow Protocol (RTMFP).  RTMFP was developed by Adobe which basically enables low latency UDP streamings and direct P2P communication between multiple Adobe Flash Players and applications. We also need to add an event listener to monitor connection activity.  This listener will allow us to know if a message has been received, a new user connects, etc. 
// create NetConnection instance
nc = new NetConnection();
nc.addEventListener(NetStatusEvent.NET_STATUS, netStatus);
nc.connect("rtmfp:");


Our listener calls the netStatus function whenever an event is dispatched by our NetConnection object.  This function is shown below.
function netStatus(event:NetStatusEvent):void{

    switch(event.info.code) {

        // The connection attempt succeeded
        case "NetConnection.Connect.Success":
             setupGroup();
             break;

        // The NetGroup is successfully constructed and authorized to
        // function.
        case "NetGroup.Connect.Success":
             // Do nothing
             break;

        // A new group posting is received
        case "NetGroup.Posting.Notify":
             mc.x = event.info.message.x;
             mc.y = event.info.message.y;
             break;

        // user joins?
        case "NetGroup.Neighbor.Connect":
             break;
 
    } // end switch
 

// end netStatus function


Our netStatus function has been set-up to monitor four activities.  The first determines if our attempt to connect to our newly created NetConnection object was successful.  If so, it will assign itself into a specific NetGroup by calling the setupGroup function.  We will discuss more on this later.

Other activities being monitored are the successful connection to the selected net group, whether a message sent by another swf has been received, and whether another user has joined the group.

Let's focus on "NetGroup.Posting.Notify", which tells us that a post or message has been received.  By accessing the NetStatusEvent object and referring to it's info property, we are able to access another property named message.  This message property is an object being passed by other connected applications.  In our example above, we have:


mc.x = event.info.message.x;
mc.y = event.info.message.y;

MC is the instance name of the circle in our demo swf.  As you can more or less see, the message we are expecting to receive from other connected movies is an object with an X and Y property.  We take the received object's X and Y properties and assign them to the same properties of our circle.  In effect, changing the position of our movieclip.

The movie with the red circle includes the following script which allows you to drag the circle around, and send its position to other connected applications.


// mc is the instance name of the red circle
mc.addEventListener(MouseEvent.MOUSE_DOWN, drag);
mc.addEventListener(MouseEvent.MOUSE_UP, drop);
 
// enable dragging
function drag(e:MouseEvent):void {
 
    this.stage.addEventListener(MouseEvent.MOUSE_MOVE, moveMe);
 
// end drag function

// Drop the object.
function drop(e:MouseEvent):void {
 
    this.stage.removeEventListener(MouseEvent.MOUSE_MOVE, moveMe);
 
// end drop function
 
// Move the object in accordind of the mouse position
function moveMe(e:MouseEvent):void {
 
    // move movieclip to mouse position
    mc.x = e.stageX;
    mc.y = e.stageY;
   
    // Save the current movieclip position
    obj.x = mc.x;
    obj.= mc.y;

    // Set sender id
    obj.sender = group.convertPeerIDToGroupAddress(nc.nearID);

    // Sends a message to all members of a group.
    group.post(obj);
 
// end moveMe function

Whenever the red circle is moved around as a result of the MOUSE_MOVE event being fired, it's X and Y properties as well as a sender id are saved into an object.  The object is then sent to the same members of the group via the post method of the NetGroup object.
 
As stated earlier, the NetStatusEvent will received this as a NetStatusEvent.info.message.  Since the object being sent contains x and y properties, these properties may be accessed in the receiving application by calling NetStatusEvent.info.message.x and NetStatusEvent.info.message.y respectively.
 
To finish up the script, let's take a look at the setupGroup function which is called when an attempt to connect to the NetConnection object is successful.
// Create a group 
function setupGroup():void {
 
    // Create a new Group Specifier object
    var groupspec:GroupSpecifier = new GroupSpecifier("test");

    // Enable posting
    groupspec.postingEnabled = true;

    // Specifies whether information about group membership can be
    // exchanged on IP multicast sockets
    groupspec.ipMulticastMemberUpdatesEnabled = true;

    // Causes the associated NetStream or NetGroup to join the specified
    // IP multicast group and listen to the specified UDP port.
    groupspec.addIPMulticastAddress("225.225.0.1:30000");

    // Constructs a NetGroup on the specified NetConnection object and
    // joins it to the group specified by groupspec.
    group = new NetGroup(nc, groupspec.groupspecWithAuthorizations());

    // Set the NET_STATUS event listener
    group.addEventListener(NetStatusEvent.NET_STATUS, netStatus);
 
// end setupGroup function
When you successfully connect to your NetConnection object, you must also create a NetGroup and join a specific group.  Only applications on the same group will be able to connect and communicate with each other.  This is determined by creating a new GroupSpecifier object.  The groupSpecifier contains certain information of your group as well as certain privileges your application may have.
 
When instanciating a GroupSpecifier object, we pass the name of the group you want to join as a string.  In our example, the name of our group is "TEST".  If the group name specified does not exist, it will be created.

As mentioned, some information grant your application privileges such as posting.  if the postingEnabled property is set to false, your application will not be able to send nor recieve posts from other connected applications.

We can now create a new NetGroup passing in out NetConnectiona and GroupSpecifier as parameters.
 
You can download the file and source code here: Flash P2P Demo.  It contains 2 files, an FLA (CS4) and an SWF.  You can open multiple instances of the SWF on your desktop to check it out.  And by the way, you'll be needing at least Flash Player 10.2
 


And that's it... the basics of P2P for your AS3 projects.  If you have any cool or exciting concepts of games or applications that can use P2P or if you have done some samples, I would definitely like to know about it.  Post a link in the comments section below!

UPDATE: Continued in Flash P2P Par Deux: Real-Time Gaming.

Post a comment:
Name
Email
Comment

40 Response(s) to Flash P2P
Philip Mabanta  ( Oct 25, 2011 - 12:59 pm )

Cool, I thought RTMFP needed a Flash Media Server to work.

So, where's the super like button?

Earl Andre Vergara  ( Oct 25, 2011 - 1:10 pm )

Just press like a couple of times... if that's even possible. :)

Ramir BPlnco  ( Oct 25, 2011 - 1:24 pm )

OMG I Have always wanted this! This is so freakishly super awesome, I changed my profile pic to Conan's epic face. :P
Thanks! sir Earl! :D

Earl Andre Vergara  ( Oct 25, 2011 - 1:27 pm )

In a sense yes... that is if you are sharing information across multiple networks. But if your applications are in the same local network, FMS is not needed.

Ramir BPlnco  ( Oct 25, 2011 - 1:30 pm )

LAN games are possible! :D DOTA remake!!

Earl Andre Vergara  ( Oct 25, 2011 - 1:35 pm )

@Ramir: "Like" the epic conan face! XD

zeratool  ( Oct 25, 2011 - 1:52 pm )

will this work 'as-is' when installed on mobile device?

Mark Paolo Cabrera  ( Oct 25, 2011 - 2:42 pm )

Holy crap batman! I thought this wasn't released yet! Great tutorial Earl!

Earl Andre Vergara  ( Oct 25, 2011 - 2:45 pm )

@Marv: Yeah, it will work as is... you can run the app (just have a movieclip named "mc" on the stage) on your mobile and open the same app on another mobile, or even on the desktop. As long as your devices are connected to the network, it will work.

Earl Andre Vergara  ( Oct 25, 2011 - 2:47 pm )

@Mark: I think it was already possible when FP10 came out, though not much was said, or no one bothered to look at P2P during that time.

Philip Mabanta  ( Oct 25, 2011 - 2:52 pm )

@Mark:

You know what this means.

Massively Multiplayer Online Slideshow 2!

Geo  ( Dec 23, 2011 - 3:59 pm )

Hi Earl,

Thanks for the nice article.

Can you please explain me how you are setting up a Peer-to-peer connection between your android mobile and the Laptop? Are you using the USB or WiFi Tethering? If we use WiFi Tethering in Android 2.2, will this application work? Im trying to use this method, but was not successful. :(

Thanks,
Geo

Earl Andre Vergara  ( Jan 19, 2012 - 10:20 am )

Hi Geo,

Sorry for the uber late reply. Wasn't able to log on for some time. The connection works via standard wifi. I have yet to see in work over Wifi tethering or bluetooth.

Gio  ( Aug 18, 2012 - 4:25 pm )

Hi Earl,
I was digging your code, but something I cannot make it trough. If I run the application on the same machine ( with 2 copy of the application running), everything of course is ok.
But when I run 1 application on iMac and another on Pc windows 7 ( under the same wifi network ), there is no way to make them communicate.
Do you have some suggestion?
By the way, thanks a lot for your code!!

Gio  ( Aug 18, 2012 - 5:28 pm )

Hello again,
probably I understand the nature of the problem, is a router issue.
At this link http://cc.rtmfp.net/ can find a connectivity checker for the RTMFP, I have several red light.... so I guess that is the problem.

Earl Andre Vergara  ( Aug 18, 2012 - 8:31 pm )

Hi Gio,

Thanks for dropping by. Be sure to check the firewall settings of your iMac to allow outside communication. Hopefully that should solve your problem.

Gio  ( Aug 19, 2012 - 12:09 am )

Hi Earl,
both firewall are disabled, I'm quite sure is a router settings issue., I will test later on another wifi network. thanks

Alan Chang  ( Nov 22, 2012 - 8:58 pm )

Hi there, I have been self learning how to make games using AS3.0 but never get over the multiplayer barrier.

Anyway, I couldn't run your example from the browser (Both on the same computer), I haven't tried downloading it or running it, but is there any additional settings I have to do before this could work?

HOS  ( Dec 22, 2012 - 6:44 pm )

Cool script! Would it be possibe to show how to make it turnbased? So the eventlisteners are on/off in each swf? When the ball is moved in the first swf the eventlistener is removed in that swf and added in the next?

Earl Andre Vergara  ( Dec 22, 2012 - 8:32 pm )

@Alan: Yeah, when you first load the swf, the Flash Player will ask your permission to allow Peer-to-peer networking, which you must allow. If no dialog box appears, just right-click on the swf and choose Global Settings. On the Playback tab, follow instructions on how to enable p2p.

Earl Andre Vergara  ( Dec 22, 2012 - 10:50 pm )

@HOS: Just to point you in the right direction:

If we had an "End Turn" button, the script will look something like this:

endTurn_btn.addEventListener(MouseEvent.CLICK, endTurnHandler);

function endTurnHandler(e:MouseEvent):void {
endTurn_btn.removeEventListener(MouseEvent.CLICK, endTurnHandler);
endTurn_btn.visible = false;

mc.removeEventListener(MouseEvent.MOUSE_DOWN, drag);
mc.removeEventListener(MouseEvent.MOUSE_UP, drop);

obj.action = "endTurn";
obj.sender = group.convertPeerIDToGroupAddress(nc.nearID);
group.post(obj);

} // end endTurnHandler function

**So after moving the ball, player clicks on End Turn button.. which then removes the EventListeners and sends an "endTurn" message. Then on your netStatus function... you will have something like:

function netStatus(event:NetStatusEvent):void{

switch(event.info.code) {
case "NetGroup.Posting.Notify":
if (event.info.message.action) {
if (event.info.m

Earl Andre Vergara  ( Jan 10, 2013 - 9:14 pm )

oops...

function netStatus(event:NetStatusEvent):void{

switch(event.info.code) {
case "NetGroup.Posting.Notify":
if (event.info.message.action) {
if (event.info.message.action == "endTurn") {
}
activateTurn();
}
break;
}

function activateTurn():void {
endTurn_btn.visible = true;

mc.addEventListener(MouseEvent.MOUSE_DOWN, drag);
mc.addEventListener(MouseEvent.MOUSE_UP, drop);
}

Earl Andre Vergara  ( Jan 10, 2013 - 9:17 pm )

So for both SWFs, one should activate the EventListeners and make the endTurn button visible, while the other should start with no eventListeners and the endTurn button invisible.

**About adding comments, they are actually filtered by the site admin before they are approved for posting. =\ So when you submit a comment, it would immediately show up until such time when the admin approves it.

Earl Andre Vergara  ( Jan 10, 2013 - 9:22 pm )

About the android-to-android not working... i can think of 3 things:

1) Be sure they are connected to the same group. In this case:
var groupspec:GroupSpecifier = new GroupSpecifier("test");
*8They both should be connected to "test."

2) One (or both) devices is not connected to the network or is connected to a different network. They must be connected to the same wifi network.

3) probably an error when installing the apps. Try uninstalling, then install again.

HOS  ( Jan 10, 2013 - 9:50 pm )

Thank you very much for the reply. If there's 3 instances running, how do I check which "users" is connected to it can take turns between them?

Regarding Android to Android I've tested like you said but it doesn't work. If I start an instance on my PC and the 2 android devices running the app it works. But not when it's only two Androids. If you make an app from your code is it then working with only Android to Android?

Earl Andre Vergara  ( Jan 10, 2013 - 11:49 pm )

Yeah, it works on Android-to-Android, Android-to-iOS, Desktop-to-Android, Desktop-to-iOS.

About having more than 2 devices connected, each device needs to have a name assigned to them; like "device1", "device2", "device3", etc. If such is the case, then you will need 2 variables to keep track of the current turn.

var Names:Array = new Array("device1","device2","device3");
var currentTurn:int = 0;

When the endTurn button is pressed, you just need to increment the currentTurn variable and target the next device by sending it's name:

endTurn++;
if (endTurn >= Names.length) endTurn = 0;

obj.action = "endTurn";
obj.turn = Names[currentTurn];
obj.sender = group.convertPeerIDToGroupAddress(nc.nearID);
group.post(obj);

Earl Andre Vergara  ( Jan 10, 2013 - 11:52 pm )

An finally, you just need to check if the message received is meant for you:

function netStatus(event:NetStatusEvent):void{

switch(event.info.code) {
case "NetGroup.Posting.Notify":
if (event.info.message.action) {
if (event.info.message.action == "endTurn") {
}
if (event.info.message.turn == myName) activateTurn();
}
break;
}

But of course, each device will need a variable "myName" with their names assigned to it:

e.g. On first device, myName = "device1"
Onsecond device, myName = "device2"
and so on.

lol  ( Mar 11, 2013 - 9:13 am )

thanks for him!

HOS  ( Mar 11, 2013 - 3:26 pm )

Sorry!!! My bad. Thank you very much for the code and suggestions.

I still can't get it to work android 2 android, though. If it's a firewall issue is not useable in apps. I can't expect users to change their firewall settings because of an app. I hope there will be a solution.

Alfred Lee  ( Jul 25, 2013 - 11:45 pm )

Hello,
I have downloaded the demo to try how is it work.
I just try to open the swf file twice and see are they sync , but it is not working. Do I need to use FMS to work or set the IP address? I cannot figure out where the problem is.

Earl Andre Vergara  ( Jul 26, 2013 - 10:06 am )

@HOS: As far as i know, firewall would be an issue if you try it on your pc but android or ios should have no firewall unless the network itself has a firewall. Actually i don't know what i'm talking about. :p I've tested on multiple devices, platforms, and networks but never had a problem with connection.

@Alfred: Did you download BOTH swfs? The one with the red circle and the other with the blue circle? When you say you downloaded the swf and opened it twice i assume you are only talking one swf? The demo needs both swfs to work.

Alfred Lee  ( Jul 26, 2013 - 10:46 am )

Thanks for your reply~~
Yes I have downloaded both swfs.
So what I need to do is open both of them?
Do you want to have the effect which is two circle moving together?
I have open them and when I move the red circle I can see no other interaction or moving on the blue side. "Two circle move together" , is that the desired effect for you?

Earl Andre Vergara  ( Jul 26, 2013 - 11:05 am )

Yes, you need to open both of them. When you move the red circle the blue circle should follow. Note that when you open the swf, flash will ask you if you want to allow P2P connections. Allow the connection and it should work okay. If you want the circles to move at the same time with no delay, at the bottom of the post you will see a link to my next post regarding realtime connections.

Alfred Lee  ( Jul 26, 2013 - 11:09 am )

When I first time downloaded them I have already tried to open two swfs. But at my computer it's completely not working. I can't figure out what the problem is. Do I need a Adobe cirrus developer key or set the IP address in the setupGroup function?
Thanks.

Earl Andre Vergara  ( Jul 26, 2013 - 11:18 am )

@Alfred: You don't need a dev key or anything like that. Can you verify what verson of FlashPlayer you are using? You need at least version 10.

Alfred Lee  ( Jul 26, 2013 - 11:23 am )

I'm using Flash Player 11.7.

(Maybe there are some errors in my setting of the computer internet connection...?)

Earl Andre Vergara  ( Jul 26, 2013 - 11:40 am )

Ok.. try renaming both swfs, then open them again. You should see a popup asking you to alliw peer connections. Make sure the checkbox is marked. Try to move the red circle.

If it still doesn't work then you can try to convert them into projectors. On the flashplayer, go to File menu and select make/create projector. You need to select a destination where the projector files (.exe) will be saved. Do this for both swfs. Once you have created both projectors, clise the swfs then navigate to the folder where the projectors were saved. Open both projectors and try moving the red circle again.

Alfred Lee  ( Jul 26, 2013 - 1:21 pm )

Oh....it still not works.......
Maybe you can send me both your flash files (.exe) to let me have a try.

louieben  ( Sep 6, 2013 - 11:27 am )

what about when I want to control multiple scenes???

kenny  ( Sep 14, 2013 - 1:58 am )

Hi earl,
it's really a great code.
I'm still confuse how to determine the air hockey paddle for each player in multiplayer so other player can't control the other paddle.
Can you help me please... :)


SEARCH
MEMBER
LOGIN
Blog
Archives