making layers repel and attract in after effects using expressions


In this tutorial, we will larn how to create an expression that will allow us to make layers repel or attract other layers.  Here's a sample of the kind of effects we will be able to achieve:

First, create a few stationary layers in your comp.  These layers will be repelled by another layer.  Then create a new layer, and keyframe its motion.  This layer will be the layer which all the other layer avoid.   Now that the setup part is done, add this expression to the position property of the layers to be repelled (the stationary ones):

avoidPos = thisComp.layer("Avoid Me").position;
maxDisplacement = 85; //maximum amount to move the layer
minDistance = 50;  //minimum distance to begin displacing at
//--
vec = avoidPos - position;
directionVec = normalize( vec );
distance = length( vec );
displaceAmt = ease( distance , 0 , minDistance , 0,  maxDisplacement  );
displacementVec = displaceAmt * directionVec;
position + displacementVec 

Be sure to pickwhip avoidPos to the layer you are trying to avoid.  Also, feel free to change the other two variables. maxDisplacement determines the maximum amount a layer can move away on a given frame, and minDistance determines how close the otehr layer must come before the layer starts moving away.  After RAM previewing your comp, you may notice that you probably didn't get the effect you were expecting.  You probably got something like this:

It seems as if the layers are being repelled like they are supposed to, but they are also returning to their original positions.  If this is what you are looking for, use this expression, but otherwise keep reading.  

Now, remove that first expression we used and add this one:

avoidPos = thisComp.layer("Avoid Me").position;
maxDisplacement = 100; //maximum amount to move the layer
minDistance = 25; //minimum distance to begin displacing at
//--
finalPos = position.valueAtTime(0);
oldDirectionVec = normalize([1,1]);
for( i = 0 ; i <= time; i+= thisComp.frameDuration ){
   try{
      vec = finalPos - avoidPos.valueAtTime( i );
      directionVec = normalize( vec );
      oldDirectionVec = directionVec;
      distance = length( vec );
      displaceAmt = ease( distance , 0 , minDistance , maxDisplacement , 0 );
      displacementVec = displaceAmt * directionVec;
      finalPos += displacementVec
      } catch ( exception ){
         finalPos += oldDirectionVec * displaceAmt;
      }
}
finalPos

You should get something like this:

Now, lets look at how this one works.  The idea behind this one is fairly simple.  On every frame, we will create a direction vector that represents the direction from the "Avoid Layer" to the "Repelled Layer."  This will be stored in the directionVec variable.  Then as the "avoided" layer gets closer to each layer the value of the displaceAmt will increase, via the the ease() interpolation method.  Lastly, on each frame, we will move the "Repelled Layer" in the direction of directionVec by displaceAmt pixels.  

The for() loop in this code is so the "Repelled Layer" can remember its previous position each frame, and thus avoid the problems in the first expression.  Lastly, this little snippet of code at the end:

} catch ( exception ){
         finalPos += oldDirectionVec * displaceAmt;
      }

Is just doing some error catching.  After Effect's will generate an expression error if you try to normalize or find the length of a vector of length zero, and this code just says if there is an error generated when calculating the direction vector, use the direction vector from the precious frame.  Note that you should not start out the "avoided layer" at the same position as any of the other layers.

If you want to make the layers attract instead of repel, just change the line that says:

vec = finalPos - avoidPos.valueAtTime( i );

to

vec = avoidPos.valueAtTime( i ) - finalPos;

Also, you might want to note that these expressions work just as well in 3d as they do in 2d.  

Download the After Effects 7.0 Project File here




Recent updates

links I like

AEnhancers forum