Reputation: 1
Anyone has a good algorithm for how to get a smooth but predictable movement from point a -> b
in 2D in any language?
I need to have one function setting the velocity each frame:
function GetVel(current_pos : Vector2, dest_pos : Vector2, current_vel : Vector2)
{
var new_vel : Vector2d;
.......
return new_vel;
}
and a corresponding:
function GetDestTime(current_pos : Vector2, dest_pos : Vector2, current_vel : Vector2 )
{
var duration : float;
.......
return duration;
}
Simply using acceleration leads up to lots of sliding so some good smoothDamp algorithm that can be predicted the exact dest time is what I need.
Any ideas?
Upvotes: 0
Views: 195
Reputation: 324
Let's assume v(0) = 0 and v(T) = 0 and, v(t) is a quadratic function which the maximum value at t = T/2.
Accordingly, we can assume the form,
Since the point moves L within T seconds, integrating v(t) from 0 to T must give L. So, we can get another equation,
Solving these equations gives,
Using these a and b, you can compute the current velocity.
It is rather long, but I made a Java toy to realize this. Please check it!
import java.awt.*;
import javax.swing.*;
public class MovePoint extends Canvas implements Runnable {
public static void main(String... args) {
Thread thread = new Thread(new MovePoint());
thread.start();
}
private static final int WIDTH = 500;
private static final int HEIGHT = 500;
public MovePoint() {
super();
this.setBackground(Color.WHITE);
this.setForeground(Color.BLACK);
this.setSize(WIDTH, HEIGHT);
JFrame f = new JFrame("Move Point");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(this);
f.pack();
f.setVisible(true);
}
private Point V;
private Point S = new Point(50, 50);
private Point E = new Point(450, 450);
private double duration = 5.0;
private double dt = 0.03;
private Image buffer;
private Graphics gBuf;
public void run() {
double t = 0.0;
V = S.copy();
while (t < duration) {
V = Point.add(V, calcVelocity(V, S, E, t, duration).scale(dt));
t += dt;
repaint();
try {
Thread.sleep(30);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.exit(0);
}
public void paint(Graphics g) {
if (gBuf == null) {
buffer = createImage(WIDTH, HEIGHT);
gBuf = buffer.getGraphics();
}
gBuf.setColor(Color.WHITE);
gBuf.fillRect(0, 0, WIDTH, HEIGHT);
gBuf.setColor(Color.BLACK);
gBuf.fillOval((int)(V.x - 5), (int)(V.y - 5), 11, 11);
g.drawImage(buffer, 0, 0, this);
}
public void update(Graphics g) {
paint(g);
}
public Point calcVelocity(Point current, Point start, Point goal, double t, double T) {
double L = Point.distance(start, goal);
double a = -6.0 / (T * T * T);
double b = 3.0 / (2.0 * T);
double s = (t - 0.5 * T);
double v = a * s * s + b;
return Point.subtract(goal, start).scale(v);
}
}
class Point {
public double x;
public double y;
public Point(double x, double y) {
this.x = x;
this.y = y;
}
public Point copy() {
return new Point(x, y);
}
public static double distance(Point p, Point q) {
double dx = p.x - q.x;
double dy = p.y - q.y;
return Math.sqrt(dx * dx + dy * dy);
}
public static Point add(Point p, Point q) {
return new Point(p.x + q.x, p.y + q.y);
}
public static Point subtract(Point p, Point q) {
return new Point(p.x - q.x, p.y - q.y);
}
public Point scale(double s) {
return new Point(x * s, y * s);
}
}
Upvotes: 2