Skip to main content
Community Expert
November 26, 2022
Answered

Detecting a collision with expressions

  • November 26, 2022
  • 2 replies
  • 1713 views

I have a layer moving along the X-axis. I have a shape layer with a simple stroke and trim paths that has the starting point of the stroke on the same X-axis. When the moving layer (m) reaches the same X value, I want the stroke to move up.  This simple expression pops the line up to 100%

 

m = thisComp.layer("Mover").position;
r = position;

if (m[0] < r[0] || m[0] > r[0] + 60)
	y = 0;
else
	y = 100;

 

There are no keyframes at the time of the collision, so using time in an ease method is not working for me. 

 

Is there some way to come up with an interpolation method that says

 

when m = r increase the value of y so that when m = r + 30, y == 100;
then as m moves from r+30 to r + 60, y changes from 100 to 0

 

If I had a keyframe where the collision occurs, it would be easy to use valueAtTime for the keyframe to create the growing and falling stroke. I can't figure out how to make it happen without a keyframe.

 

Any suggestions would be appreciated.

 

This could also be helpful in animating a countdown so as the numbers go from 10 to zero a line would grow and shrink instead of just blinking when each number is reached.

This topic has been closed for replies.
Correct answer Dan Ebberts

I'm having trouble picturing what you're trying to do and how it's affected by the number of points in the star. I think a more detailed description would help.


This is one idea. It assumes your value for Points only jumps in whole number increments. The expression checks to see when it last changed and when it next changes and uses the time in between those changes to animate from 0 to 100. I have no idea if that's what you're looking for, but it might give you some ideas:

 

n = content("Polystar 1").content("Polystar Path 1").points;
tMin = null;
tMax = null;
t = time - thisComp.frameDuration;
while(t >= inPoint){
  if (n.valueAtTime(t) != n){
    tMin = t+thisComp.frameDuration;
    break;
  }
  t -= thisComp.frameDuration;
}
t = time + thisComp.frameDuration;
while(t <= outPoint){
  if (n.valueAtTime(t) != n){
    tMax = t-thisComp.frameDuration;
    break;
  }
  t += thisComp.frameDuration;
}
if (tMin != null && tMax != null){
  ease(time,tMin,tMax,0,100);
}else{
  0;
}

 

2 replies

Dan Ebberts
Community Expert
Community Expert
November 26, 2022

Maybe something like this:

m = thisComp.layer("Mover").transform.position[0];
r = position[0];
m < r + 30 ? ease(m,r,r+30,0,100) : ease(m,r+30,r+60,100,0)
Community Expert
November 26, 2022

Thanks, Dan. Perfect for my application.

Community Expert
November 26, 2022

How about a situation where you are only working with whole numbers? Something like this:

 

n = content("Polystar 1").content("Polystar Path 1").points;
t = time?;
tMin = ???;
tMax = ???;
if (n == 3)
	ease(t, tMin, tMax, 0, 100)
else
	0
	

 

With no keyframes and no values to look for that gradually change over time how would you ease between values?

Mylenium
Legend
November 26, 2022

Why not simply measure the distance from the stroke to the box with length()? Fed into a linear() expression that could give you the driver/ driven relation you seem to be after. Real collision detection would be way too complicated, though Dan would probably have some code handy that uses temporal integration and then makes the whole thing respond.

 

Mylenium