Getting
started
This tutorial will be based on the Basic Chat we built in an earlier tutorial.
A few changes in the stage and symbols used will be necessary. I have the new
.fla file with these changes applied, ready for you to download here. Using
this file, we are going to go step by step through all of the new code you
will need, in order to work with room variables.
Introducing new stuff
IMPORTANT:
Rooms by default do not support
user variables. You have to set userVariablesEnabled
= true when
creating a room, if you want them to work. ElectroServer is designed this
way in purpose.
User variables are part of every user object that exists inside the socket
server and follow the user everywhere, in every room he enters and they show
up in the user list object. So, if user variables were always on, there would
be many cases where lots of redundant data is transferred from the server
to every client. In order to prevent that from happening, by default user
variables are not enabled in a room.
So, make sure you enable user variables now, by modifying the joinRoom() function in the main
timeline, frame Login and function makeRoom() inside the popup moveclip,
frame NewRoom. Add this line:
roomObj.userVariablesEnabled
= "true";
We will be introducing some new stuff here, so we are going to need a
few new variables. Go to the Actions layer, frame labeled Login and type this code
at the very top:
// useful variables
var color:Number;
var myUsername:String;
Now modify the loginClicked() function:
function loginClicked() {
      myUsername = username_txt.text;
      if (myUsername.length > 2 && myUsername.length < 15)
{
             Key.removeListener(keyListener);
            Â
             es.loggedIn = loggedIn;
             es.login(myUsername);
             gotoAndStop("LoggingIn");
      }
}
We’ll need the variable myUsername later on.
We’re going to need an object to store some information about all users
in the room. We’ll also need a color for your smiley.
var users:Object = {};
color = Math.ceil(Math.random()*8);
createAvatar(myUsername, color, Math.ceil(Math.random()*(board._width
- 30)), Math.ceil(Math.random()*(board._height - 30)));
board is the name of the light blue board on the stage, where
all avatars will be displayed.
The function in the last line of code creates an avatar. Let’s see how
it works.
function createAvatar(username:String, color:Number,
x:Number, y:Number):Void {
      if (users[username]
!= undefined)
             return;
     Â
      users [username]
= {};
     Â
      var user:Object
= users[username];
      user.clip = board.attachMovie("smiley",
username, board.getNextHighestDepth());
      user.clip.gotoAndStop(color);
      user.x = user.clip._x = x;
      user.y = user.clip._y = y;
      user.clip.username_txt.text = username;
      user.color = color;
}
First of all, if a user with this name already exists, the function simple
does nothing. This prevents us from overwriting an existing user.
A new object is created inside users, named after username. A new movieclip
is attached on the stage, inside the board movieclip. This is
the movieclip of the avatar. If you open the symbol named LNK_Smiley inside
the library, you’ll see that it has 8 frames, with each one having a smiley
of different color. There is also a dynamic textfield, named username_txt.
The code above tells the smiley movieclip to go the
a specific frame, according to the color property and sets the user’s
name in the textfield. The avatar is moved to x and y.
The color, movieclip, x, and y properties are stored
in the user object for future use.
So, if we say it was you that entered the room and your avatar was created,
you would want the rest of the people in the room to see it as well. User variables is our friend here. Let’s see how we are going
to use them.
Just below the createAvatar() function call, type
this:
createUserVariables();
Let’s create this function.
function createUserVariables():Void {
      es.createUserVariable("color",
color);
      es.createUserVariable("coords",
users[myUsername].x+","+users[myUsername].y);
}
Very easy to use, createUserVariable() takes two parameters,
a name and a value for the variable you want to create. The value is always
stored as a primitive (string or number), so make sure you only use primitives
with user variables. If you need to have more complex data types, you will
have to serialize them into strings and pass the string as a parameter.
So, in the code above, we create two user variables, one for the color
and one for the coordinates of the avatar. We could have separate x and y variables, but it
would bring more trouble than convenience. Now, as soon as the message travels
to the server, these two variables will be stored together with your username,
inside the user object and they will be accessible by anyone inside the room.
Now, let’s modify the showUsers() function, so that
it displays everyone’s avatar.
function showUsers(userlist:Array, type:String, lastUser:String):Void
{
      if (userlist == undefined)
             userlist = es.getUserList();
     Â
      userListBox.dataProvider = userlist;
     Â
      switch (type) {
            Â
             case "userjoined":
             createAvatar(lastUser);
             break;
            Â
             case "userleft":
             deleteAvatar(lastUser);
             break;
            Â
             case "all":
             case undefined:
             createAllAvatars(userlist);
             break;
            Â
      }
     Â
      for (var i:String in userlist) {
             var user:Object = userlist[i];
             var username:String = user.Name.value;
             var temp:Array = user.userVariables.coords.split(",");
             users[username].x = temp[0];
             users[username].y = temp[1];
             users[username].color = user.userVariables.color;
      }
      updateAvatars();
}
First of all, showUsers() is called as a callback
for es.userListUpdated.
userListUpdated has 3 parameters: userlist, type and lastUser. type shows the type of
the update of the user list. It can be equal to “userjoinedâ€, “userleft†or “allâ€. “all†is
when you first join a room, “userjoined†is when a user just joined the room
and “userleft†is when a user leaves the room. We are going to need all of
them shortly.
Remember from previous tutorials, we used to call showUsers() near the top of the
code of the Chat frame. We call the function with no parameters, so
the very first time userlist, type and lastUser will all be undefined.
That’s why we set userlist
= es.getUserList() if the userlist parameter is undefined and that’s also
why we have a case undefined inside the switch(type) block.
There are quite a lot of new function calls here, so let’s see all the functions  one by one.
function createAllAvatars(userlist:Array):Void {
      for (var i:String in userlist) {
             var username:String = userlist[i].Name.value;
             var color:Number = userlist[i].userVariables.color;
             var x:Number = userlist[i].userVariables.x;
             var y:Number = userlist[i].userVariables.y;
             createAvatar(username, color,
x, y);
      }
}
One important thing here is .userVariables.
A userlist returned by ElectroServer is an array with many user objects.
User variables are stored in an object named userVariables, inside each user
object. So we can access them by this syntax: userObject.userVariables.variableName.
After we get all user variables, we call createAvatar(), passing along these variables and the avatar is created.
User enters or leaves the room
When an existing user leaves the room, his avatar should be removed. That’s
what deleteAvatar(lastUser) does in case “userleft†inside showUsers().
function deleteAvatar(username:String):Void {
      removeMovieClip(users[username].clip);
      delete users[username];
}
As you see the function removes the smiley movieclip from the stage and
deletes the user object.
If a new user enters the room, while you are already in it, you need to
make a new avatar for him. That’s why we call createAvatar(lastUser) in case “userjoined†inside showUsers().
Back to showUsers() again, we update
the user objects according to the data we get from the user variables and
then we call updateAvatars(), which updates all
avatars on the board.
function updateAvatars():Void {
      for (var i:String in users) {
             var user:Object = users[i];
             if (user.x != undefined && user.y
!= undefined) {
                    user.clip._x = user.x;
                    user.clip._y = user.y;
             }
      }
}
Avatar movement
We are now going to make the avatars move around.
Near the top of the frame code, just below createUserVariables() add these two lines:
initMouseControl();
initTweens();
function initMouseControl():Void {
      board.onPress = function():Void {
             mouseClicked();
      }
      board.useHandCursor = false;
}
When you click on the board, mouseClicked() is called.
function mouseClicked():Void {
      var newX:Number = _root._xmouse - board._x;
      var newY:Number = _root._ymouse - board._y;
      var x:Number = users[myUsername].x;
      var y:Number = users[myUsername].y;
     Â
      users[myUsername].sourceX = x;
      users[myUsername].sourceY = y;
     Â
      users[myUsername].x = newX;
      users[myUsername].y = newY;
      es.updateUserVariable("coords",
newX+","+newY);
}
It stores two new properties inside the local user object, sourceX and sourceY. They will be used
for the tweening.
As soon as you click, the new coordinates x and y are sent to the server,
updating your user variables coords. An event will be
sent from the server to each one in the room, notifying them that a user’s
variable has changed. We’ll get to that shortly.
For now let’s see the tween functions.
function initTweens():Void {
      this.onEnterFrame = moveAvatars;
}
function moveAvatars():Void {
      for (var i:String
in users) {
             var user:Object
= users[i];
             var clip:MovieClip
= user.clip;
             var floor:Function
= Math.floor;
             clip._x += (user.x - clip._x)/6;
             clip._y += (user.y - clip._y)/6;
      }
}
moveAvatars() will execute on every frame, moving all avatars towards
the new coordinates. The movement is eased-out.
It’s time to see how we can capture the change of a user variable of someone
in the room.
function userVariableUpdated(user:Object, type:String,
name:String):Void {
      var username:String = user.Name.value;
      if (username == myUsername) return;
     Â
      switch (name) {
            Â
             case "color":
             users[username].color = user.userVariables.color;
             users[username].clip.gotoAndStop(user.userVariables.color);
             break;
            Â
             case "coords":
             var temp:Array = user.userVariables.coords.split(",");
             userPositionUpdated(username,
temp[0], temp[1]);
             break;
      }
}
es.userVariableUpdated =
userVariableUpdated;
ElectroServer calls a function named userVariableUpdated every time a user
variable changes.
userVariableUpdated has 3 parameters: user, type and name.
- user is the object of the user whose variable changed.
- type can be either “created†or “updatedâ€.
- name is the name of the variable that was created or
updated.
In the function above you see that there are 2 different case statements
inside the switch block.
The first one will update the color of the avatar, according to the variable
color of the user object. It’s called only once (for each user), when a user
first enters a room.
“coords†will be called every time a user clicks
on the board and changes his position. The new coordinates are sent to the
server and the server notifies all users in that room that an avatar needs
to be repositioned.
Well, that’s it! Now you’ve got a cool 2D Avatar Chat. Try it with a bunch
of users in the same room and you’ll have nice smiles flying all around!
Keys to remember
- User variables
are attached to a user and follow him around wherever he goes.
- A room can have
user variables either enabled or disabled. By default user variables are
disabled. You have to set userVariablesEnabled
= true when creating a room, if you want them to appear in the user list
of the current room.
- Every time a
single user variable is updated, userVariableUpdated is fired by the server. If your users have 5-6
different variables and you need to change 3 of them in the same time,
3 different events will be fired. It might be more efficient to group some
of them together, like we did here with coords. This way you minimize the traffic between the
server and the client and gain in speed and redundant code.
- User
variables can help you do some pretty nice stuff. A user can have age,
country, favorite color, score, lag time, time zone and many other useful
variables stored, which can be used to display useful data in a chat, game
or application.