We are about to switch to a new forum software. Until then we have removed the registration on this forum.
Edit: I think I'm pretty happy with this solution: https://forum.processing.org/two/discussion/comment/99885/#Comment_99885
Edit2: I also like the solution in my last post: https://forum.processing.org/two/discussion/comment/123690/#Comment_123690
x = 0;
y = 0;
hueSlider = 0;
function setup() {
createCanvas(640, 480);
colorMode(HSL);
slider = createSlider(0, 360, 0);
}
function draw() {
hueSlider = lerp(hueSlider, slider.value(), 0.01)
background(hueSlider, 50, 70);
fill(120, 50, 50);
x = lerp(x, mouseX, 0.05);
y = lerp(y, mouseY, 0.05);
ellipse(x, y, 50, 50);
}
Original post:
Hi! I really miss having a simple easing function built into p5. I'm a beginner, and my attempts of implementing one myself have failed so far.
I've used vvvv quite a bit before, which has a simple to use "Damper" node/function, which is used like this:
damper(value, duration)
(Or maybe smoothTransition(value, duration)
would be a better name?)
Calling ellipse(damper(mouseX, 1.5), damper(mouseY, 1.5), 50, 50)
and moving the mouse quickly would mean the ellipse would first go towards the new position rapidly, and slow down as it approaches, going from start to finish in 1.5 second, resulting in a nice and smooth transition.
The vvvv damper's outputs are the damped value, the acceleration and the velocity.
In the p5 world, the most common solution I come across is something like this:
x += easingFactor * (mouseX - x)
It works fine, but it's not very elegant, and for each thing I want to apply easing to, I have to create a new variable:
function setup() {
createCanvas(640, 480);
colorMode(HSL);
slider = createSlider(0, 360, 0);
newhue = 0;
}
function draw() {
background(newhue += 0.05 * (slider.value() - newhue), 50, 50);
}
I would like to use p5 in teaching to give kids a fun introduction to programming. However, this awkward and verbose way of achieving something seemingly simple seems off-putting, and contradictory to p5's general user-friendliness.
I would prefer not having to create any new variables, and rather enter something like this:
background(damper(slider.value(), 3), 50, 50);
Here's my failed attempt (without the time parameter for now):
function setup() {
createCanvas(640, 480);
colorMode(HSL);
slider = createSlider(0, 360, 0);
}
function draw() {
background(damper(slider.value()), 50, 50);
}
function damper(value) {
newValue = value;
newValue += 0.05 * (value - newValue);
return newValue; // No easing happens
}
Alternatively, there's the option of getting a better selection of curves (linear, easeInQuad, easeOutQuad, easeInOutQuad, etc.): https://gist.github.com/gre/1650294
This approach involves having a variable t going from 0.0 to 1.0 in x seconds. I can work with it when pressing a button, but my use case is for things that run continuously.
I guess I could store values in a fixed size array, using a.unshift() and a.push(val), and apply some kind of calculation to its numbers. However, it seems to me that this approach would also require new variables to be created.
Thanks for reading! - Kristian
Answers
@kristianp89 --
It looks like you are on the right track. I believe that a vvvv damper isn't a function -- it is an object, which is to say that it does contain an envelope (array) of values. There is no way for a computer to simulate a damper without saving those values.
So you probably want to define a Damper class which contains such an array, then create a new Damper, as per the objects tutorial.
https://p5js.org/examples/objects-objects.html
If your students cut and paste the damper class, then they will be able to use it with a simplified syntax, and you won't need to fiddle with global variables.
Okay, so I think I'm getting there, but my solution only works with one variable. What am I missing?
http://Bl.ocks.org/GoSubRoutine/fa085945d45152786698f44a9523ccac
That's a cool example, but it requires the creation of variables (dampers[0]), going through a for loop, and it's not very readable.
I've been looking around some more, and I'm actually quite happy with this solution:
I wish I didn't have to create an extra variable for everything I want to apply easing to, but overall I think this is pretty good.
Here's the video I got it from:
http://Bl.ocks.org/GoSubRoutine/fa085945d45152786698f44a9523ccac
[Code below] Further down is my preferred solution, written in native JS, but applicable to p5. It's not the solution I wanted, but I think it's the most readable one so far.
For those who haven't seen this before, this is called "easing"(?), and it's is a way of achieving smooth animations. (I just call it "damping", because that's what I know from vvvv.)
For most cases, this technique looks far better than instant movements or linearly increasing variables.
Basically, each time the damping function is called, x.damped gets 5% closer to x.target.
In this example, x.target is changed from 0 to 100. x.damped then gets incremented by 5% of what's remaining to the target, each frame:
Paste into .html file:
A possible improvement would be to loop over an array or an object in the damping function, but I like being able to use x.damped instead of dampArray[2].damped or dampObject.x.damped for example.
Here's one that I really like. I can just add variables to the string!
It's a little less flexible than the manual approach, and it doesn't read as nicely, but there's less repetition.