2

I'm trying to make clouds move out of frame and than appear again from the other side.

var vel = 100;
var pInit = position.valueAtTime(0)[0]; // initial position of a cloud
var tInit = (thisComp.width-pInit)/vel; // time it takes to cross the right border starting from init position
var tFull = (thisComp.width+width)/vel; // time it takes to cross the frame starting behind the left border
var offset = 0;
tBound = tInit;

if(time > tBound) {
  tBound += tFull;
  offset += thisComp.width+width;
}

[value[0]+time*vel-offset,value[1]]

First time if statement works as expected. tBound becomes 40s and it offsets cloud. But when time gets bigger than 40 nothing happens. Neither offset variable gets bigger nor tBound. If statement doesn't work anymore. What's the problem here?

1
  • the if statement only returns true or false. When time >= 2*tBound you're still only offsetting the value once.
    – stib
    Mar 27, 2017 at 1:18

2 Answers 2

1

I don't think you need an expression to achieve this. You could just loop a cloud moving across the screen inside a precomp.

0
1

You're making it hard for yourself basing it on the time rather than the position. Here it is using the bounds of the comp rather than the time it takes to reach the bounds of the comp, which just made my head hurt.

The best tool for looping variables is the modulus % operator:

var vel = -100;
var pInit = position.valueAtTime(0)[0]; // initial position of a cloud
var initOffset = width/2 + thisComp.width;
[(pInit - initOffset + time * vel) % (thisComp.width + width) + initOffset, value[1]]

The modulus operator returns the remainder when you divide the left side by the right side. So as the value gets smaller than 0 - (thisComp.width + width) it will loop back to zero. There's a slight problem, in that the value starts positive, so we subtract an offset to it which we then add back again outside of the modulus.

Note that I made the velocity -100, to better reflect what's going on. In fact you can make this expression work for layers looping either way by changing the value of the offset, depending on whether the velocity is positive or negative, meaning that you have a universal looping expression, where only the velocity needs editing:

var vel = 100;
var pInit = position.valueAtTime(0)[0]; // initial position of a cloud
var initOffset = (vel < 0)? width/2 + thisComp.width : 0 - width/2; 
[(pInit - initOffset + time * vel) % (thisComp.width + width) + initOffset, value[1]]

I used a ternary operator (looks like (expression)? value-if-true: value-if-false, which is shorthand for if()then{}else{}) on line 3 to change the initial offset for positive or negative velocities.

Another way of achieving this is to use a while() loop:

var vel = -100;
var pInit = position.valueAtTime(0)[0]; // initial position of a cloud
x =pInit  + time * vel;
while (x < 0- width/2){ x += thisComp.width + width}
[x, value[1]]

In your initial expression when you applied an offset the offset was only applied once, so the loop only happened once. So on line 4 I use a while() loop to add the offset until the value goes back into the range needed.

Once again it can work for clouds going both ways, by checking for the value being greater than the width of the comp:

var vel = -100;
var pInit = position.valueAtTime(0)[0]; // initial position of a cloud
x =pInit  + time * vel;
while (x < 0- width/2){ x += thisComp.width + width;}
while (x > thisComp.width + width/2){ x -= thisComp.width + width;}
[x, value[1]]

The downside to this is that if your frequency is very high and your comp very long it could take a while to evaluate, because it has to go through the loop multiple times. If you had hundreds of layers doing this it could cause AE to get rather laggy.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.