Exit
  • Global community
    • Language:
      • Deutsch
      • English
      • EspaƱol
      • FranƧais
      • PortuguĆŖs
  • ę—„ęœ¬čŖžć‚³ćƒŸćƒ„ćƒ‹ćƒ†ć‚£
  • ķ•œźµ­ ģ»¤ė®¤ė‹ˆķ‹°
0

How to work with an array?

Community Beginner ,
Nov 25, 2014 Nov 25, 2014

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; // Is not working...

/*

this is the error:

Screen Shot 2014-11-25 at 22.49.51.png

*/

//start_correct =  Math.floor(str* 0.04*100)/100;

//end_correct =  Math.floor(str+1]* 0.04*100)/100;

/*

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* 0.04*100)/100) "Hi";

}

*/

TOPICS
Expressions
1.4K
Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Nov 25, 2014 Nov 25, 2014

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

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Beginner ,
Nov 26, 2014 Nov 26, 2014

Hi Dan,
Heading the wrong road could very well be!

So basically I want this in a expression:

Screen Shot 2014-11-26 at 10.30.18.png

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:

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Nov 26, 2014 Nov 26, 2014

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

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
Nov 26, 2014 Nov 26, 2014

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!

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
Nov 26, 2014 Nov 26, 2014
LATEST

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.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines