Exit
  • Global community
    • Language:
      • Deutsch
      • English
      • Español
      • Français
      • Português
  • 日本語コミュニティ
  • 한국 커뮤니티
0

Detecting a collision with expressions

Community Expert ,
Nov 26, 2022 Nov 26, 2022

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.

TOPICS
Expressions
1.7K
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

correct answers 2 Correct answers

Community Expert , Nov 26, 2022 Nov 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)
Translate
Community Expert , Nov 26, 2022 Nov 26, 2022

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){
    tMi
...
Translate
LEGEND ,
Nov 26, 2022 Nov 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

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, 2022 Nov 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)
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, 2022 Nov 26, 2022

Thanks, Dan. Perfect for my application.

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, 2022 Nov 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?

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, 2022 Nov 26, 2022

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.

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, 2022 Nov 26, 2022

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;
}

 

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, 2022 Nov 26, 2022

Thanks, Dan. I need this because I have data-driven animations that don't use any keyframes, and a lot of them jump between whole numbers. Some of the animated maps and charts I'm working on have about 200 shapes that need to react to changing digits and moving layers. Your solutions will save me many hours of trying to keyframe all those layers. I just threw in a thisProperty. propertyGroup(3) to create a c variable and added && n == c to the last if statement for Trim Paths on an ellipse named 1, moved the duplicates (all 12 of them) to the proper positions, and I now have an ellipse that draws around a text layer that is moving along a path and is driven by a JSON file that lights up 12 different numbers.  You have saved me hours.

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 27, 2022 Nov 27, 2022

Now I'm curious. Could the expession have referenced the JSON file itself? That would probably be more efficient than the frame-by-frame sniffing I put in there.

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 27, 2022 Nov 27, 2022
LATEST

That's a very interesting idea. 

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