In this second chapter of the
"Simple Chat" application I'd like to
discuss a little more in detail some aspects of the code created
so far. The previous article focused its attention on how to quickly
build a simple chat application and we intentionally left out some
topics that deserve some extra explanation.
[ CONNECT - LOGIN - JOIN ]
As you have noticed we have taken three main actions in the previous
At first we try to establish a connection to the server
using the its ip address and port.
This is just like knocking at someone's door. You don't enter in
the house, you just ask if there's anybody at home.
In case you don't get any responses then you won't be able to ask
If the server responded you can tell who you are and see if the
server accepts you.
In our case you will always be accepted unless you use a user name
that is already in use.
Once you're "inside" you will be able to choose which
room you want to enter.
This is determined by the "zone" in which you asked to
log in. You can think of "zones" as if they were different
houses, each of them
with its different set of rooms. Some can be very small with a
few rooms and others can be huge and with many many rooms.
Once these three steps are taken successfully you're enabled to
interact with all the other users.
Below follows a table with the typical request-response pattern
that you would normally use to do the connect-login-join:
- // Most important thing to do: create an instance of the SmartFoxClient class
- server = new SmartFoxClient()
|Event fired by Server
|server.connect(ip, port, zone)
|server.joinRoom(roomId) or server.autoJoin()
|onJoinRoom() or onJoinRoomError()
[ THE ROOMLIST: ROOM AND USER Objects ]
Two of the most important SmartFoxServer events are called onRoomListUpdate()
What makes them special is the fact the they populate some data
structures in the SmartFoxClient object and I'd
like to take a deeper look at it.
The following picture represents the SmartFoxServer internal data
structure and you have already seen it in the first part of this
The server (at the root of the diagram) holds a list of zones,
each running a different application.
Each zone contains a list of rooms which in turn contain users.
While the server always sees all this big structure, the client
has a smaller perspective as every user is always connected in just
one zone at a time. So the SmartFoxClient object
is populated with a list of Rooms (those owned by the zone in which
we are connected) and every Room will have its own list of users.
The picture below shows this in detail:
The roomList is an array and it is populated with Room objects
when the onRoomListUpdate event is fired: each Room object can be
accessed using the methods shown under the Room Object.
The userList is an array and it is populated with User objects
when the onJoinRoom event is fired: each User object can be accessed
using the methods shown under the User Object.
If you go back to the previous article and source code, you will
notice that we already used these objects and methods but now
you should have a better understanding of what's going on "behind
the scenes" and be able to experiment on your own.
[ HANDLING ERRORS ]
One important thing to consider in every project is how to manage
unexpected conditions and errors.
Also sometimes it is necessary to stop the normal flow of the application,
for example to get some input from the user and we would also like
our UI to behave in a different way (i.e. disable certain part
of it until the user submits data).
In our "Simple Chat" demo we can get
two types of errors:
- a login error, if you try to enter with an already
existing user name
- a join error, if you try to join a room that's
To test these conditions, try launching two instances of the "Simple
Chat" sample and log in with the same name:
the second time a dialog window will popup in the middle of the
screen and the rest of the application will be grayed out.
The application will restore its state when you will press the "OK" button.
We'll use this simple system quite a lot in all the next tutorials
every time we will need a dialog box:
- sending a private message
- entering a password protected room
- creating a new room
- creating a new game room
- showing system and error messages
You can find the code that handles the dialog boxes under the "connect"
label in the source fla of the "SimpleChat"
Mainly we use two functions: showWindow(), hideWindow()
- function showWindow(linkageName)
- _global.isBusy = true
- disabler._visible = true
- var win = _root.attachMovie(linkageName, linkageName, 9999)
- win._x = (stageW / 2) - (win._width / 2)
- win._y = (stageH / 2) - (win._height / 2)
- return win
The "linkageName" argument is the linkage
identifier of the symbol in the library, so if you plan to add you
own custom windows always remember to export them for "Actionscript".
If you inspect the library in the .FLA you will find a "_windows"
folder with all the dialog boxes needed by the application and if
you right-click (win) or ctrl-click(mac) on each of them you will
notice that they all have a linkage id.
The _global.isBusy boolean is tested everytime
a button in the interface is pressed. This way we can disable all
buttons in the GUI just by setting this global variable to "true".
The variable called "disabler" refers
to a movieclip (check the layer called "disabler") that
will cover the entire stage with a semi-transparent black square
(this enforces the idea that the main interface has been temporarily
The code continues by attaching the dialog box movieclip on stage,
then the clip is centered in the screen and a reference to it
is returned by the function so you can furtherly manipulate it.
Now double click on the "errorWindow"
movieclip in the library and select the "OK" button then
open the Actionscript panel (F9).
You will notice that we have just one command, closeMe(), and you
will find it's code in the main timeline of the "errorWindow" mc.
This command invokes the hideWindow() function
in the parent timeline passing the movieclip instance name as an
argument. This way the hideWindow() method can
destroy the window and re-enable the GUI controls.
In the next tutorials we will use also input dialog boxes and
we will use almost the same approach. The only thing we'll change
the button will not directly call the closeMe() function, instead
it will call a function in the main timeline that will read the
data and then invoke the hideWindow() method.
See you in the next article.