Not too long ago, as I was looking up the internet for interesting game concepts, I stumbled across this amazing game and was immediately blown away by it’s level of detail and interaction. It was so much for a flash game that I thought if it wasn’t as popularly rated as it is now, it would be a complete devastation for the game developers.

One of the interesting dynamics introduced in the game is the movements of the people. They are really just for eye candy but I thought they are completely essential to bring the game to life. I decided to take a closer look at each of the characters, take them apart and try to replicate them. This is what I got:

Preparing the body parts
Every once in a while I had been telling myself to try on some animated joint movements but only now I was seriously working on it. So I started on the blank stage and began drawing some body parts shapes. Convert each of these body parts into movieclip symbols.

Animated joint movements

Once you have all the body parts as movieclip symbols, you will need another small red circle moveclip about 5px by 5px which will be used to mark the joint position. So create that now.

Now, that we have the body parts and the joint, you need to adjust the origin for each them. Simply double click the body part, and you will now be inside the movieclip and you can shift the shape around abit. What you need to do is to shift the shape so that the origin is at the position where the body part would rotate about. For example, for the torso (body) body part, the rotating position is at the waist; for fore arms, the rotating position will be at the elbows. As for the small red circle, shift it so that the origin is at the center of the circle.

Animated joint movements

Note that the steps we have just taken does not actually cause the body parts to rotate about the intended positions. So we need to correct that now. We go back to the root timeline by double clicking on the empty space around the shape, or clicking on Scene 1 on the timeline. Now use the free transform tool (Q) and click on the body part movieclip we have just adjusted. You will see that the symbol is now selected with 8 square handles around it and a white circle in the centre. The white circle represents the rotation point, so just drag the white circle to the adjusted origin marked by the cross. If you have done that correctly, you will see it is rotating as intended if you now rotate the symbol with the same tool.

Animated joint movements

What we have done so far is to define the rotation point for the body parts. Now we need to define the joint point for each body part. Go into each of the body parts again, this time copy and paste the red circle movieclip symbol inside the body part movieclip. Adjust the red circle such that it is at the joint position of the body part. For example, the fore arm will have the joint position at the wrist, and the torso (body) will have 3 joint positions: at the left and right shoulders and at the neck. As a final step, give the red circle movieclip an instance name “joint”.

Animated joint movements

With all the symbols set up, we are ready to piece them up altogether! Go back to the root timeline where all the body parts movieclips are and move them around to their correct positions where the hands and legs are supposed to be. Select all of them now, and make it into a big human movieclip symbol. With this human symbol, you can quickly create many humans on stage later with customised movements of their own.

Animated joint movements

Getting into the Action
Now we need some place to write our actionscript and there are two of them. I’m going to define 2 general functions in the root timeline. This following piece of code is written on a single layer, on the first frame of the root timeline.

// Helper functions
// Returns a random integer betweentwo integers</code>
function randRange(min:Number, max:Number):Number {
	var randomNum:Number = Math.floor(Math.random()*(max-min+1))+min;
	return randomNum;
}
// general tweening function with callback capabilities
function Animate(obj, ppt, from, to, dur, callback) {
	var tween_handler:Object = new mx.transitions.Tween(
                                       obj,
                                       ppt,
                                       mx.transitions.easing.Regular.easeOut,
                                       from, 
                                       to,
                                       dur,
                                       true);
	tween_handler.onMotionFinished = callback;
}

The next block of code will be in the first frame of the timeline of the human movieclip symbol.

#include "motion.as"

Now we will create a new actionscript file by going file > new, and start coding away.

// motion.as
// Handlers
Body.onEnterFrame = function() {
         /*
	Body is the instance name of the
	torso body part movieclip.
	This function ensures that the
	body parts are always attached
	to the joints to the correct places
	*/	
	// left side
	var joint = jointPoint(Body.jointLeft);
	LArm._x = joint.x;
	LArm._y  = joint.y;
	var joint = jointPoint(LArm.joint);
	LFore._x = joint.x;
	LFore._y  = joint.y;
	var joint = jointPoint(LFore.joint);
	LHand._x = joint.x;
	LHand._y  = joint.y;
	
	// right side
	var joint = jointPoint(Body.jointRight);
	RArm._x = joint.x;
	RArm._y  = joint.y;
	var joint = jointPoint(RArm.joint);
	RFore._x = joint.x;
	RFore._y  = joint.y;
	var joint = jointPoint(RFore.joint);
	RHand._x = joint.x;
	RHand._y  = joint.y;
};

ThinkNextAction();
function ThinkNextAction() {
	/* This function will allow the human to begin
		his next action via a random number generator */
	_switch (_root.randRange(0, 4)) {
	case 0 :
		MoveRelax(ThinkNextAction);
		break;
	case 1 :
		MoveWaist(ThinkNextAction);
		break;
	case 2 :
		MoveScratchHead(ThinkNextAction);
		break;
	default :
		MoveRandom(ThinkNextAction);
		break;
	}
}
// Random movement
function MoveRandom(callback) {
	// LEFT
	var rotationTo = _root.randRange(-90, 45);
	_root.Animate(LArm, "_rotation", LArm._rotation, rotationTo, 1, null);
	var rotationTo = _root.randRange(-rotationTo, rotationTo);
	_root.Animate(LFore, "_rotation", LFore._rotation, rotationTo, 1, null);
	//RIGHT
	var rotationTo = _root.randRange(-45, 90);
	_root.Animate(RArm, "_rotation", RArm._rotation, rotationTo, 1, null);
	var rotationTo = _root.randRange(-rotationTo, rotationTo);
	_root.Animate(RFore, "_rotation", RFore._rotation, rotationTo, 1, null);
	var rotationTo = 0;
	_root.Animate(RHand, "_rotation", RFore._rotation, rotationTo, 1, callback);
}
// Scripted movement: move hand to waist
function MoveWaist(callback) {
	// LEFT
	var rotationTo = 0;
	_root.Animate(LArm, "_rotation", LArm._rotation, rotationTo, 1, null);
	var rotationTo = 0;
	_root.Animate(LFore, "_rotation", LFore._rotation, rotationTo, 1, null);
	//RIGHT
	var rotationTo = 20;
	_root.Animate(RArm, "_rotation", RArm._rotation</code>, rotationTo, 1, null</code>);
	var rotationTo = -45;
	_root.Animate(RFore, "_rotation", RFore._rotation, rotationTo, 1, null);
	var rotationTo = 0;
	_root.Animate(RHand, "_rotation", RFore._rotation, rotationTo, 1, callback);
}
// Scripted movement: move hand to head
function MoveScratchHead(callback) {
	// LEFT
	var rotationTo = -20;
	_root.Animate(LArm, "_rotation", LArm._rotation, rotationTo, 1, null);
	var rotationTo = 45;
	_root.Animate(LFore, "_rotation", LFore._rotation, rotationTo, 1, null);
	//RIGHT
	var rotationTo = 90;
	_root.Animate(RArm, "_rotation", RArm._rotation, rotationTo, 1, null);
	var rotationTo = -135;
	_root.Animate(RFore, "_rotation", RFore._rotation, rotationTo, 1, null);
	var rotationTo = -135;
	_root.Animate(RHand, "_rotation", RFore._rotation, rotationTo, 1, callback);
}
// Scripted movement: stand straight
function MoveRelax(callback) {
	// LEFT
	var rotationTo = 0;
	_root.Animate(LArm, "_rotation", LArm._rotation, rotationTo, 1, null);
	var rotationTo = 0;
	_root.Animate(LFore, "_rotation", LFore._rotation, rotationTo, 1, null);
	//RIGHT
	var rotationTo = 0;
	_root.Animate(RArm, "_rotation", RArm._rotation, rotationTo, 1, null);
	var rotationTo = 0;
	_root.Animate(RFore, "_rotation", RFore._rotation, rotationTo, 1, null);
	var rotationTo = 0;
	_root.Animate(RHand, "_rotation", RFore._rotation, rotationTo, 1, callback);
}
// Convert and calculate the correct _x _y 
// for the joints
function jointPoint(joint) {
	var myPoint:Object = {x:joint._x, y:joint._y };
	joint._parent.localToGlobal(myPoint);
	this.globalToLocal(myPoint);
	return myPoint;
}

Extensibility
There were several considerations before I end up with the current structure I am writing now. In fact this is the 5th version of how the symbols and actionscripts are organised in their approperiate places. My main aim is to achieve a high level of extensibilty with regards to the possibilities of the flash game i took reference from.

With this setup, you can create different sets of motion.as files and include them for each individual human movieclip you duplicate. Wrting different MoveXXXXX functions will give each individual their unique movements. You can also use different frames inside human movieclip to give it a different visual look, like the skin color, hair, clothes, shoes.

Try it, and show off your results to me!