任何人都有一个很好的算法,可以在任何语言中从2D a -> b
点获得平滑但可预测的移动?
我需要有一个功能设置每帧的速度:
function GetVel(current_pos : Vector2, dest_pos : Vector2, current_vel : Vector2)
{
var new_vel : Vector2d;
.......
return new_vel;
}
和相应的:
function GetDestTime(current_pos : Vector2, dest_pos : Vector2, current_vel : Vector2 )
{
var duration : float;
.......
return duration;
}
简单地使用加速导致大量滑动,因此可以预测精确定位时间的一些好的smoothDamp算法是我需要的。
有什么想法吗?
答案 0 :(得分:1)
假设v(0)= 0且v(T)= 0,v(t)是二次函数,t = T / 2时的最大值。
因此,我们可以采用表格
由于该点在T秒内移动L,因此将v(t)从0整合到T必须给出L.所以,我们可以得到另一个等式,
求解这些方程式,
使用这些a和b,您可以计算当前的速度。
这是相当长的,但我做了一个Java玩具来实现这个目标。请检查一下!
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);
}
}