Category: Flash & AS


AS3 passing argument list to functions

It appears that argument list passing is not very well documented in the flash docs for whatever reason. But we know it is possible because the trace() funcion is one such function that accepts an argument list.

the syntax for such a function is acheived by using the tripledot keyword as such

function ExampleConcatString(... str:String):String
{
        var newStr:String = "";

        for(var i = 0; i < str.length; i++)
        {
                newStr+= str[i];
        }

        return newStr;
}

Also, intuitively, argument list should come after default arguments which are before required arguments as such:

function SomeFunc(required:String, optional:Object = null, ... arglist:*)

As much as some FF fanboy is going to defend and deny, and putting the blame on the coder, this is still going to be a BUG!

When an HTML document includes the doctype declaration at the top of the page, the swf embeded in the document will not render properly when the its height is set to 100%. The result is an swf rendered beyond the top border of the window as though the CSS top attribute has been set to a negative value. However, when the doctype is removed, the swf will render correctly just as IE does.

I only realised this issue after serveral hours of debugging and totally hate it when its not my fault. So I went ahead to search online to confirm if it is a bug indeed. I came across a forum (which I will not point out) where another poor victim posted this same issue. One guy came along, whom I presume is an FF fanboy, and replied along the lines of “its your own fault” without proposing any solutions! I totally hate this kind of posters who just come along to insult you on something irrelevant to the issue at hand.

After the poor guy replied, the FF fanboy went on to argue that without specifying the container’s width and height, firefox (or the swf) is not going to know how big is 100%. So you need to set the width and height for all the parent and grandparent containers including the body and html tag!

Well, so that is the solution in overcoming the BUG! And yes, it’s a bug because if you just removed the doctype, everything renders fine.

animated joint movements

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
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, rotationTo, 1, null);
	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!

Powered by WordPress | Theme: Motion by 85ideas.