Activity › Forums › Adobe After Effects Expressions › Expression to make a boat “ride” on top of generated waves?
-
Expression to make a boat “ride” on top of generated waves?
Posted by Max Palmer on May 10, 2012 at 8:50 pmSo what I want to do is pretty simple. I have an animation of a man rowing a boat, and under neath I have a plain solid rectangle with some wiggle expressions on a wave warp effect, which create a nice random wave effect.
Is there an expression I can use to make it so that the boat bobs up and down a little bit in sync with the waves?
Thanks.
Max Palmer replied 14 years, 2 months ago 3 Members · 26 Replies -
26 Replies
-
Dan Fredley
May 10, 2012 at 10:39 pmIf the waves are consistent then you can just set 2 keyframesat the top and bottom then set the following expression:
(might have to play with ease settings on keyframes)
loopOut(type = "pingpong")Dan Fredley
-
Max Palmer
May 10, 2012 at 11:02 pmUnfortunately, it’s not. The animation is seeded so that it has a natural random feeling.
-
Dan Ebberts
May 10, 2012 at 11:10 pmIt might be possible to calculate the wave height at any point and time. What are your wave warp settings and expressions? What’s the layer number of the wave layer?
Dan
-
Max Palmer
May 10, 2012 at 11:40 pmDan- first off, love your site. I’ve used the examples several times, and it was actually my first go-to place when trying to figure this particular problem out. Thanks!
Here is a screenshot of my wave setup. I made a small expression with a wiggle, part of which is pickwhipped to a null with some keyframes on it. The reason I did this is so that I could increase the waves later in the animation (a storm will happen).
-
Dan Fredley
May 11, 2012 at 12:46 amchange the sampleLayer to your water layer and then try applying the following to the boat position.
L = thisLayer;
targetPosition = L.toWorld(L.anchorPoint);
sampleLayer = thisComp.layer(thisComp.numLayers);
for (i=0; i<thisComp.height;i++) {
alphaCheck = sampleLayer.sampleImage(sampleLayer.fromWorld([targetPosition[0],i]), radius = [.5,.5]);
if (alphaCheck[3]<1) {
continue;
} else {
alphaPosition = [0,i];
break;
}
}
newWorldPos = L.fromWorld(L.toWorld(alphaPosition));
[value[0],newWorldPos[1]]
Dan Fredley
-
Dan Fredley
May 11, 2012 at 12:49 amactually try this–expression got screwed up somehow during copy/paste
L = thisLayer;
targetPosition = L.toWorld(L.anchorPoint);
sampleLayer = thisComp.layer(thisComp.numLayers);
for (i=0; iL = thisLayer;
targetPosition = L.toWorld(L.anchorPoint);
sampleLayer = thisComp.layer(thisComp.numLayers);
for (i=0; iDan Fredley
-
Dan Fredley
May 11, 2012 at 12:58 amLet’s try this one more time:
L = thisLayer;
targetPosition = L.toWorld(L.anchorPoint);
sampleLayer = thisComp.layer(thisComp.numLayers);
for (i=0; i < thisComp.height;i++) {
alphaCheck = sampleLayer.sampleImage(sampleLayer.fromWorld([targetPosition[0],i]), radius = [.5,.5]);
if (alphaCheck[3] < 1) {
continue;
} else {
alphaPosition = [0,i];
break;
}
}
newWorldPos = L.fromWorld(L.toWorld(alphaPosition));
[value[0],newWorldPos[1]]Dan Fredley
-
Dan Fredley
May 11, 2012 at 1:13 amjust noticed you have a shape layer. You’ll need to precomp the shape layer with the slider or use a solid instead
Dan Fredley
-
Max Palmer
May 11, 2012 at 1:00 pmThat works! Amazing. Thank you SO much. My last thing I need to do is find a way to make the boat rotate slightly as it bobs, so in other words, when it bobs up the boat rocks back, and when it bobs back down, it rocks forward. Is that easy to do?
-
Dan Fredley
May 11, 2012 at 1:35 pmI wrote a better expression in case the boat layer reaches the edge of the composition. I suggest precomping the boat and water layer in a 2x wide comp to animate the boat across a full comp otherwise the expression won’t work past the edge of the main comp. I hope that makes sense:
Final position expression:
target = thisComp.layer("Controller").effect("Boat")("Layer");
targetWorldPos = target.toWorld(target.anchorPoint);sample = thisComp.layer("Controller").effect("Ocean")("Layer");
for (i = 0; i < height; i++){
if (sample.sampleImage([clamp(targetWorldPos[0],0,thisComp.width), i], [0.5, 0.5], true)[3] > 0){
top = [0,i];
break;
} else {
top = [0,thisComp.height];
}
}newWorldPos = target.fromWorld(target.toWorld(top));
[value[0],newWorldPos[1]]To be able to rock the boat:
Final rotation expression:
target = thisComp.layer("Controller").effect("Boat")("Layer");
targetWorldPos = target.toWorld(target.anchorPoint);sample = thisComp.layer("Controller").effect("Ocean")("Layer");
offset = -10;for (i = 0; i < height; i++){
if (sample.sampleImage([clamp(targetWorldPos[0]+offset,0,thisComp.width), i], [0.5, 0.5], true)[3] > 0){
top = [0,i];
break;
} else {
top = [0,thisComp.height];
}
}newWorldPos = target.fromWorld(target.toWorld(top));
offsetPos = [target.position[0]+offset,newWorldPos[1]];for (i = 0; i < height; i++){
if (sample.sampleImage([clamp(targetWorldPos[0],0,thisComp.width), i], [0.5, 0.5], true)[3] > 0){
top = [0,i];
break;
} else {
top = [0,thisComp.height];
}
}targetWorldPos = target.fromWorld(target.toWorld(top));
boatPos = [target.position[0],targetWorldPos[1]];radians = Math.atan2(boatPos[1] - offsetPos[1],boatPos[0] - offsetPos[0]);
radiansToDegrees(radians);This is going to be really slow to calculate. You should bake all of these expressions. Then after you bake the rotation put this expression on it otherwise it will be really choppy:
Final baked rotation expression:
smooth(.5,10)Dan Fredley
Reply to this Discussion! Login or Sign Up

