Copy link to clipboard
Copied
Hi,
I'm working on an expression that will start an animation at random or on defined frame numbers in a layer.
I'm using an array to put all the frame numbers in.
I'm currently "developing" in a textlayer expression:
seedRandom(1,true);
id = 0;
range = 4;
var str = "";
var tmp = 0;
length = 100 / range;
str = "22|44|61|86";
/* Random str: */
/*
while (id < range){
start = (length * (id+1)) - length;
end = length * (id+1);
tmp = Math.floor(random(start ,end));
str = str + tmp + "|";
id += 1;
}
*/
// To create an array I use this but I wanted to use an array in the while statement... See below...
str = str.split("|");
// Im not sure this is correct but it gives me and "j" value that I can use...
j = Math.floor((time*25)/10);
// Now for the problem part:
str[1]; // Is working..
str
/*
this is the error:

*/
//start_correct = Math.floor(str
//end_correct = Math.floor(str
/*
function between(x, min, max) {
return x >= min && x <= max;
}
if (between(time, scorrect, ecorrect )) {
// Linear or Ease function...
}
*/
// Another problem I discoverd was when filling an array: newarray = random(100) gives an error.
// So not using:
// var newarray = [];
// This does work:
/*
for (var j = 0; j < str.length-1; j++){
if (time == Math.floor(str
}
*/
Copy link to clipboard
Copied
My hunch is that you might be headed down the wrong road. It's not clear exactly what you're trying to do, but I'm guessing there's an easier way to do it. Maybe you could describe more about how you want it to work rather than how you're trying to implement it...
Dan
Copy link to clipboard
Copied
Hi Dan,
Heading the wrong road could very well be!
So basically I want this in a expression:
![]()
Expression for TimeRemap:
On (random) frame numbers go from timecode (toggle holdkeyframe) 00:00:00:00 tot 00:00:01:00 wait a random amount and go from 00:00:01:00 tot 00:00:02:00 and so on...
Keep doing this 2/3/4/5 times... I'll use a slider for this.
Expression for X Rotation:
On (random) frame numbers go from 0 to 180 wait a random amount and go from 180 to 360. and so on...
Keep doing this 2/3/4/5 times... I'll use a slider for this.
I saw you doing something similar:
http://motionscript.com/expressions-lab-ae65/random-grid-movement.html
But I didn't quite get that so I started from scratch...
And got stuck on the array part...
I can maybe do something like this with random numbers..
0;
if ((time*25) >= 25 && (time*25) <= 75) linear(time, 1, 2, 0, 100);
if ((time*25) >= 75 && (time*25) <= 100) linear(time, 3, 4, 100, 200);
if ((time*25) >= 100 && (time*25) <= 150) linear(time, 5, 6, 200, 300);
It would be nice if could have a (dynamic) range:
range = "22|44|61|86"; (or more)
And away to fill these if then linear/ease functions with this range.
0;
if ((time*25) >= a && (time*25) <= b) linear(time, a/25, b/25, 0, 100);
if ((time*25) >= b && (time*25) <= c) linear(time, b/25, c/25, 100, 200);
if ((time*25) >= c && (time*25) <= d) linear(time, c/25, d/25, 200, 300);
if ((time*25) >= d && (time*25) <= e) linear(time, d/25, e/25, 200, 300);
but I rather have something like this:
array = "22|44|61|86";
for i = 0; i <= array.length-1; i++ {
if ((time*25) >= array && (time*25) <= array[i+1]) linear(time, array/25, array[i+1]/25, i, i+1);
}
But This needs an extra variable Time... Because else only the last array item would be shown...
Another challenge is the toggle hold is this possible with TimeRemap and Linear function?
Anyway I hope this clarifies my question a bit?
Any idear why the array isn't working for me?
I want to do this (see video) with a lot more layers...
Partial render of my project:
Copy link to clipboard
Copied
I think I see what you're trying to do. This may not be exactly right, but this is how I would approach it. Since you have two expressions (x rotation and time remapping) that need the same random information, you need to publish it where they can both get to it. Since you need two pieces of info (current segment number and starting frame of the current segment) I'd use a point control with an expression like this:
fMin = 22;
fMax = 86;
fCur = timeToFrames(time);
f = 0;
n = 0;
seedRandom(index,true);
while (f <= fCur){
fPrev = f;
f += Math.floor(random(fMin,fMax+1));
n++;
}
[n-1,fPrev];
Then you could use something like this for x rotation:
fTrans = 30; // no. of transition frames
fPrev = Math.round(effect("Point Control")("Point")[1]);
n = Math.round(effect("Point Control")("Point")[0]);
if (fPrev > 0){
d = timeToFrames(time) - fPrev;
ease(time,framesToTime(fPrev),framesToTime(fPrev+fTrans),(n-1)*180,n*180);
}else
value
and something like this for time remapping:
fTrans = 30; // no. of transition frames
fPrev = Math.round(effect("Point Control")("Point")[1]);
n = Math.round(effect("Point Control")("Point")[0]);
if (fPrev > 0){
d = timeToFrames(time) - fPrev;
framesToTime(d < fTrans/2 ? n-1 : n)
}else
0
Hope that helps.
Dan
Copy link to clipboard
Copied
First, some info about working with arrays.
There is no reason to create your "str" array of values the way you are. DON'T do it like this:
var str = "1|2|3|4"; // a string literal, why would you do this?
str = str.split("|"); // splitting a string literal into an array of substrings? why???
DO do it like this:
var str = [1, 2, 3, 4]; // an array of four integer values. Much better!
It does basically the same thing except it's easier to declare and manipulate, plus you're ensuring that your array contains actual integer number values instead of strings. Arrays also have tons of useful methods, especially push() and sort(). So if you want to add a number to an existing array, just do this:
var str = [1];
str.push(2); // str = [1, 2]
str.push(3); // str = [1, 2, 3]
str.push(4); // str = [1, 2, 3, 4]
Sort() will change your array to be in order. BUT, be careful when sorting numbers. Whenever you're sorting an array of numbers, include the following function at the top of your expression:
function sortNumber(a, b) { return a - b; } // include this or else sort() will work alphabetically instead of numerically
Then call sort() like this on your array:
var str = [1, 10, 2, 20];
str.sort(sortNumber); // sort numerically, str = [1, 2, 10, 20]
Now on to generating random frame numbers. Firstly, there is no reason to use integers and frame numbers for your purpose. In fact the whole way you're going about it is kind of weird. After Effects expressions generally keep track of time in terms of seconds, not frames. The global "time" variable is a decimal number representing the current time in seconds, such as "1.25" or "5.12". Forget trying to round numbers and do weird math - just randomly generate frame times and use those.
So if you want to generate an array of numbers that will represent your random frame times do it like this:
function sortNumber(a, b) { return a - b; } // include this or else sort() will work alphabetically instead of numerically
var times = []; // this will be your array of frame times
seedRandom(0, true); // seed random numbers so they're unaffected by time
for(var i = 0; i < numberOfRandomTimesYouWant; i++) {
times.push(random(thisComp.duration)); // add a random time between 0 and the comp duration to times[]
}
times.sort(sortNumber); // sort your times from least to greatest, numerically
// Now that you have an array of random times, it's a bit trickier to figure out which "breakpoint" you've passed. There are a lot of ways to do this, here's one solution:
var seedNum = 0;
while(times.length > 0 && time > times[0]) {
seedNum = times.shift(); // remove the first time in the array because we've already passed it; store it in seedNum
}
// after the while loop, seedNum will be equal to the last "breakpoint" passed
seedRandom(seedNum, true);
var yourValue = random(); // generate whatever random value you want here!
Well that's pretty much it I guess. Good luck!
Copy link to clipboard
Copied
I neglected to take into account the easing you want to do but that would be possible by implementing some of the solution that Dan mentioned above.
Get ready! An upgraded Adobe Community experience is coming in January.
Learn more