PlayerIO

The fastest way to build online games without breaking a sweat.

Building Flash Multiplayer Games

This tutorial is also available in a pure flash version..

Table of contents
1 - Introduction 8 - Synchronization
2 - Game Basics 9 - Interpolation
3 - Turn Based Games 10 - Latency
4 - Network Architectures 11 - Tips & Tricks
5 - Security 12 - Game: Turn Based
6 - Example Game 13 - Game: Realtime uninterpolated
7 - Real Time Games 14 - Game: Realtime interpolated

Game Basics.

The simplest multiplayer game: Hello World.

multiplayer game communication

In case you are unfamiliar with your programming history and conventions, Hello World is a program that simply prints out "Hello World". As such, it's an effective learning tool. The "Hello World" program in our case will send a message to the server and the server will respond "Hello World". We will then trace this message out and through this simple example, you will learn everything you need to know about communicating with your multiplayer server!

You can download the source for this example here.

Let us look at the code needed to do this on the flash side of things. All we have here are a couple event listeners, a couple functions and a few calls to PlayerIO functions. But, A closer look is needed....

So what just happend?

As always, this statement is needed to use the custom functions and datatypes such as Message and Connection.

In these lines, we are using the Connection object and joining a room. The Connection object is used to handle the connection to the server and provide useful features such as transmission of data.

The first line is our gameID. You'll need to sign up to Player.IO and create a game in the admin panel to get a gameID. Don't worry, it's free, fast and painless.

Then, we connect and ask for "handleConnect" to be called on successful connection. In the handle connect method, we are given the Client object. This object is used to communicate with Player.IO. We'll keep our interactions to client.multiplayer which is used to manage, join and create multiplayer rooms.

In this case, we just join the room "test" or create it if it does not already exist by using the createJoinRoom() function

Notice the line that sets client.multiplayer.developmentserver to "127.0.0.1:8184"; this tells the game that it should use the local development server when running the game. When we want to run the game live on Player.IO's game servers, we'll have to remove the line.

This brings us to our join function, which is quite simple in itself. We are passed our multi-purposed connection object at long last. This function does 2 things: first it sends a message to the server using connection.Send() then it waits for a response through the use of event listeners. connection.addMessageHandler (type,function) will wait until you receive a message of that type then call the specified function. In this case, our function is just a simple trace.

As you can see, once a connection is established, sending or receiving a message is very easy. It only requires a single call to connection.Send(). Now, let us see how to set up our server to return our message properly.

Here is the bulk of the server-side code. Why, this is emptier then a really boring cocktail party! Other then empty template functions, we've only actually got one line of code!

But let's take a look at all the code.

The only question left is what this single line does.

The function that holds it, GotMessage(), is called every time the server receives a message from a player. It then passes us two parameters, the player who sent the message and the contents of the message itself.

The single line that composes this function (player.Send()) does almost the exact same thing as connection.Send() from our flash code. Only, we are sending a message of type "Hello World" from the server to the specified player.

Another option we could have used is the Broadcast() function. The only difference is that instead of sending to a single person, you send the message to all the players in the room. In this case, the exact syntax would have been Broadcast("Hello World")

Again, here is the source for our Hello World program.

Messages are important to all aspects of our games. Messages are simple and dynamic, just the way we like them.

Let us delve into what composes a message...

The message

There are 2 main parts to a Message. The first is used exclusively in our Hello World example, the message type. This is a string that tells you what the message is about. For example it could be "move" or "attack".

The second part of a message is the actual data. Each message can have multiple pieces of data attached to it. These pieces of data tend to be numbers and/or other miscellaneous information.

A visualization of a message would be as such:

The kind of message sent is entirely situational dependant. In our earlier example  we could get away with messages that held no data, only types.

To give actual functionality, however, you will want to attach data to you messages. For example, if you wanted to send the message that you were moving to x=200 and y=300 then the message would have to look like:

The code to send this message is just as easy as the code for our previous messages. Just add the data as extra arguments to the send function as such:

connection.Send("move",200,300)

Receiving and reading messages

Sending is easy. But we also must be able to extract and use the data that was sent from the other side. For the most part, this is the same on both the client and the server, the key differences being the different datatypes that are used in AS3 and C#. This causes slight syntax differences so it is advised you refer to the server-side documentation and client-side documentation for the exact syntax.

Imagine we could be sent one of the 3 following messages...

Which tell us to move, give us points or tell us we got killed, respectively.

The code to handle these 3 messages would look something like:

The first 3 lines are our listeners. They wait for a message and call a function when it is received. ie. "gotMove" would be called on a "move" message. To get and use a particular piece of data from the message, we do so like it was an array. The first index is 0, second index is 1.. etc. To extract, we use the function get<dataType>(index). For example, a string at index 0 would be getString(0) or an Integer at index 1 would be getInt(1)

So, now we know how to code on both the client and the server, we know how to send messages to the server and how to make it send messages back, we know how to handle messages that are sent to us and how to use the data that is sent.

Does this mean that we have all we need to make a multiplayer game?

Yes and no. We are finished covering the logistics of how to make a game, but a game isn't just about 1001101011 traveling from one computer to another, it's a complex system! Do not underestimate the importance of proper systems in this regard either. The network can be a cruel and unrelenting beast to overcome, with pitfalls and traps for the unwary and unknowing.

The majority of these difficulties occur in real-time games due to the wonderful thing called latency. But we must walk before we can run and we will not look at real-time games just yet. First, we will look at the easier, but potentially just as powerful world of turn-based games.



Table of contents
1 - Introduction 8 - Synchronization
2 - Game Basics 9 - Interpolation
3 - Turn Based Games 10 - Latency
4 - Network Architectures 11 - Tips & Tricks
5 - Security 12 - Game: Turn Based
6 - Example Game 13 - Game: Realtime uninterpolated
7 - Real Time Games 14 - Game: Realtime interpolated


About the author

Ryan Brady is a Canadian developer who is currently going to the university of Waterloo. When he isn't fooling around with friends or dealing with an ungodly amount of course work, he likes to design and build games.

Two of the things Ryan likes most above all else are sarcasm and irony. Thus, he likes other people when they have a sense of humor and don't take offence at playful stabs and teasing. Otherwise, people tend to think Ryan hates them and/or the entire universe.

Subscribing to the "Work hard, Play hard" mindset, Ryan is always on the move. There are not enough hours in the day to do everything he wants to do (which is quite a bit). As a habit, Ryan designs more things then he has time to make. Alphas and proofs of concepts are his bread and butter though he always wishes he could make them into full games.

Every so often, you will see Ryan with a full beard on his chin. This commonly refereed to as Schrodinger's beard as you never know if Ryan will have it when you see him next. He re-grows it in under a week.

Every 4 months, Ryan has a co-op term so he moves around quite a bit. He might be living in Canada one month then be living in San Fran the next. You will never know when Ryan will be at large in your area next (until it is too late).