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

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.