ElectroServer OverviewDeveloper's BlogElectroServer DownloadsShowcasing ElectroServer contentElectroServer DocumentionElectroServer Support
500 users license
$700
ES3 User Variables
Author: Dimitrios Bendilas

We are going to build a simple-yet-cool 2D avatar chat, using user variables. Users will be presented as little smiles with their username on top of them, on a board on the stage. When a user clicks anywhere on the board, his avatar will tween to the new position. This will be visible in every other user in the same room. There will be 8 different colors for the smiles and each user will get one randomly as soon as they login.
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.