AS2 text cypher

I was recently asked to create a Flash animation that would cypher random numbers until resolving, one character at a time, on a pre-definted word or phrase. I could have keyframed it, but it made sense to write a function so that the word or phrase could just be edited at any point. Here's what I came up with.

Oops, really sorry, you need flash to see this demo. You can still check out the code though : )

The big idea

The way I decided to create it was to create an multi-dimensional array containing each character, and next to each character a number that was the amount of time to wait until showing its letter. So, with the word Dave it would look like this:

D 3 seconds
a 6 seconds
v 9 seconds
e 12 seconds

Or in ActionScript

(("D",3),("a",6),("v",9),("e",12))

The basic idea is that every frame, the numbers next to the letters are all decreased by 1.. or any number we specify. If a number becomes less than 0 then the corresponding letter will be shown instead of a random number.

It has lots of arguments to make life easier for tweaking and changing.

So, with a textbox on the stage we're ready to go! For this example the textbox has an instance name of "target_textbox".

stop();
restart_butt._visible = false;
cypher(
"Some ActionScript 2.0 from djave.co.uk", //this is the text that animates
true, //from numbers to letters (true) or frome letters to numbers(false)
20, //delay before start in frames
1, //time between letters resolving, if its 1 then every frame a new number will 'resolve'
1, //how many frames between all the numbers going random
target_textbox, //the dynamic textbox instance name
7, //random numbers to cycle from 1 to.... this number
finished //the function you want to do after its finished, it crops up here...
);
// ... and it crops up here.
function finished()
{
//add functionality to restart button
restart_butt.onRelease = function(){_root.gotoAndPlay(1);};
restart_butt._visible = true;
}
function cypher(characters, uncypher, time_until_start, time_between, frequency, textbox, random_from_1_to_this_number, oncomplete)
{
// we create an empty mc to attach an onEnterFrame to. by attaching it to this, rather than the _root, it means we can have,
// like, 7 of them at a time, and we can delete them one at a time - unlike _root where if you'll end up deleting the lot. this means if you wanted to
// you could call this function on tonnes of textboxes at the same time.
var mc = _root.createEmptyMovieClip(textbox + "clip", _root.getNextHighestDepth());
// chop up that string into an array
var characters_array = characters.split("");
// measure the length
var char_len = characters_array.length;
// create an array of timings based on the variables given earlier
var timings = [];
//for each element in the characters array (which we got from the string)
for (var i = 0; i < char_len; i++)
{
// create an array of numbers, each one spaced out by the amount of time we specified earlier
timings.push(time_until_start + (time_between * i));
}
// The array that will hold all the letters and timings
var all = [];
// for each character again...
for (var i = 0; i < char_len; i++)
{
// pair off each character with the a timing from the arrays we've made :)
all[i] = [characters_array[i], timings[i]];
}
var count = 0;
mc.onEnterFrame = function(){
// a timer
count ++
// if we've gone past the amount of time specified in the arguments...
if(count > frequency)
{
// reset the timer
count = 0;
// begin to count how many of our letters have finished the process...
number_finished = 0;
// for all our letters
len = all.length;
for (var i = 0; i < len; i++)
{
// if they have finished randoming (with 5 frames of 'padding')
if(all[i][1] < -5)
{
// add to total finished
number_finished += 1;
};
}
// if the number of finished animations = the number of letters
if(number_finished == len)
{
// you can uncomment this trace if you want to see when it thinks its finished
// trace("(finished " +characters+")");
// if you specified it, do the function you asked to it here:
oncomplete();
// stop doing this
delete mc.onEnterFrame;
// be tidy and remove the movieclip we made with the onEnterFrame on it.
mc.removeMovieClip()
}
else
{
// otherwise shred the cycle function
cycle(textbox);
}
}
}
function cycle(textbox){
// the output string is going to store the final string we show, first we want it to be empty (this happens every frame)
output_string = "";
// for all the items in the array
for (var i = 0; i < len; i++) {
// take away one from the number next to each letter
all[i][1] --;
// if the number of frames to random is still greater than 0
if(all[i][1] > 0){
// we did a thing earlier to say if we want to cypher or uncypher it. this if statement just checks that, and does the correct one (both really similar)
if(uncypher == true)
{
// this bit just says, if there is a space there, put a space, not a number. This splits the sentence up in to nice chunks, rather than just tonnes of numbers
if(all[i][0] == " ")
{
// add it on the end
output_string += " ";
}
else
{
// add the random number
output_string += Math.ceil(Math.random()*random_from_1_to_this_number);
}
}
else
{
// check this out. the number next to the letter ie (D, 0) is zero or less, so add the actual letter this time, not the random number.
output_string += all[i][0];
}
}
else{
// this whole section is the equal and exact opposite of the above.
if(uncypher == true)
{
output_string += all[i][0];
}
else
{
if(all[i][0] == " ")
{
output_string += " ";
}
else
{
output_string += Math.ceil(Math.random()*random_from_1_to_this_number);
}
}
}
}
// fill the textbox with the output
textbox.text = output_string;
}
}
// Thank you, you've been a wonderful audience, tip your waiter and try the fish. Goodnight.