How to make an object smoothly transition to a new location?

Hello I am trying to make a program in which an ellipse is redrawn at any point in the canvas where the mouse is clicked, although I am stuck on one problem. I am trying to get the ellipse to move smoothly from point A (the ellipses old position) to point B ( new ellipse location where mouse is clicked)

I have gotten far enough that I can update the ellipses X and Y origin, and the ellipse updates to the new position in an instance, but I can’t make it animate to it’s new location.

Thanks for your help, here is my code for this program so far:

``````int ballX = 250;
int ballY = 250;
int ballDi = 50;

void setup()
{
size(500,500);
}

void draw()
{
background(0);
moveball();
drawball();
}

void mouseClicked()
{
ballX = mouseX;
ballY = mouseY;
}

void moveball()
{
}

void drawball()
{
ellipse(ballX,ballY,ballDi,ballDi);
}
``````
1 Like

The simplest way is to make an linear interpolation between your target position and your actual position using lerp(). Take a look : https://processing.org/reference/lerp_.html

So you can do the basic trick with a fixed coefficient but the transition still be rough

``````float ballX = 250;
float ballY = 250;
float ballDi = 50;
float targetX,targetY;
void setup()
{
size(500,500);
}

void draw()
{
background(0);
moveball();
drawball();
}

void mouseClicked()
{

targetX = mouseX;
targetY = mouseY;
}

void moveball()
{
ballX = lerp (ballX, targetX, 0.1);
ballY = lerp (ballY, targetY, 0.1);
}

void drawball()
{
ellipse(ballX,ballY,ballDi,ballDi);
}
``````

But if you want to have a smoother moving, with a sort of easing effect, you have to add a coef wich change during the interpolation :

``````
void draw()
{
background(0);
if ( targetX != ballX) i ++ ;
else i = 0 ; //reset the value if target is reached
moveball();
drawball();
}
``````

With this way, I increment i while the circle isn’t on target position.
Then I map this value between 0 and 1, or others values that are between 0 and 1 (because lerp need a coefficient between 0 and 1).

``````  float coef = map(i,0,100,0,0.7); //100 is a abrbitrary value, but it seems near the good value to have a great easing
ballX = lerp (ballX, targetX, coef);
ballY = lerp (ballY, targetY, coef);
``````

So, because my value coef change, the speed of the circle also.

Entire code below if you need it :

``````float ballX = 250;
float ballY = 250;
float ballDi = 50;
float targetX,targetY;
int i = 0;

void setup()
{
size(500,500);
}

void draw()
{
background(0);
if ( targetX != ballX) i ++ ;
else i = 0 ;
moveball();
drawball();
}

void mouseClicked()
{

targetX = mouseX;
targetY = mouseY;
}

void moveball()
{
float coef = map(i,0,100,0,0.7);
ballX = lerp (ballX, targetX, coef);
ballY = lerp (ballY, targetY, coef);
}

void drawball()
{
ellipse(ballX,ballY,ballDi,ballDi);
}
``````
4 Likes

i made a NoGame using PVector
try it and see how the movement looks
( for me it look very natural, i trained air- / gun / pistol when i was young )

``````// https://discourse.processing.org/t/bug-with-arraylist/5949
// 11/2018 kll  / my first game ever, good its not really a game
// make a arraylist of pvector points
// calc shortest distance to the next target, aim, fire + remove the point from array

int idt, pmax = 10;
ArrayList<PVector> points = new ArrayList<PVector>();     // list of points
PVector target = new PVector(0, 0);                       // position of cross line
boolean theend = false, shoot = false;

int k = 0, kmax = 30;  //firing circles
float tdist, newdist, speedf = 0.04;   // speed factor multiplied with distance gives realistic targeting movement

void setup() {
size( 300, 300);
for (int i = 0; i < pmax; i++) points.add(new PVector(random(-width/2, width/2), random(-height/2, height/2)));
//for ( PVector p : points ) println(p);
println("targets: "+points.size());
}

void draw_lines() {
stroke(200, 0, 0);
line(target.x, -height/2, target.x, height/2);
line(-width/2, target.y, width/2, target.y);
}

void draw_points() {
for (int i = 0; i < points.size(); i++) {
if ( i == idt ) stroke(200, 0, 0);
else noStroke();
fill(0, 200, 0);
ellipse(points.get(i).x, points.get(i).y, 8, 8);
}
}

int get_nearest() {
tdist = width;                              // init to max
for (int i = 0; i < points.size(); i++) {
newdist = dist(points.get(i).x, points.get(i).y, target.x, target.y);
if ( newdist < tdist ) {
tdist = newdist;
idx = i;
}
}
return idx;                                 // give index of nearest target
}

void aim() {
if ( idt > -1 ) {
PVector waytotarget = points.get(idt).copy();
waytotarget.sub(target);
if ( waytotarget.mag() > 0.5 ) {                     // thats close enough
waytotarget.setMag(waytotarget.mag()*speedf);      // calc faster to short step in that direction
target = target.add(waytotarget);                  // change target
} else {
if ( !shoot ) println("shoot at "+idt);            // only print
shoot = true;
points.remove(idt);
}
} else {
println("i win, but now i am alone!");
theend = true;
}
}

void fire() {                                   // only if shoot = true
fill(200, 100, 0);
stroke(255, 0, 0);
strokeWeight(3);
ellipse(target.x, target.y, 2*k, 2*k);        // growing red circle
strokeWeight(1);
k++;
if ( k >= kmax ) {
shoot = false;
k = 0;
}
}

void show_end() {
fill(0, 200, 0);
rect(-50, -25, 100, 40);
fill(200, 0, 0);
text(" I WIN ! ", -20, 0);                    // well, what a wonder if you play alone and targets not move
}

void draw() {
background(200, 200, 0);
translate(width/2, height/2);
if ( !theend ) {
draw_lines();                               // cross lines
draw_points();                              // all points fix pos, same size / red stroke for next target
idt = get_nearest();                        // next ( nearest ) target
if ( !shoot )      aim();                   // not walk while firing
else               fire();                  // some show / red circles
} else show_end();                            // all over, no play again button
}

``````

and a other example for “easing”

2 Likes

Awesome! Thanks for the help!