如何每隔一段时间计算一条直线上的点

How to calculate points on a line at intervals

我正在编写一个游戏,并希望射弹每帧每隔一段时间从一个位置移动到下一个位置。

我一直在尝试确定事物的斜率截距法,我越来越接近了,但我被卡住了。

到目前为止,这是我的代码:

animationFrame = refresh;
    double x, y, xPerF; //Values for drawing
    double m, b; //Value for slope and y-intercept
    double x1, x2, y1, y2; //Values for the targets
    x1 = getCenterX();
    x2 = Canvas.target[shotTarget].getCenterX();
    y1 = getCenterY();
    y2 = Canvas.target[shotTarget].getCenterY();
    xPerF = Point2D.distance(x1, y1, x2, y2)/animationSpeed;
    //Calculate slope
    if(x2>x1) m = (y2-y1)/(x2-x1);
    else if(x2<x1) m = (y1-y2)/(x1-x2);
    else m = 0;
    //Calculate the y-intercept
    b = m * x1 - y1;
    if(b<0) b = -b + Canvas.myHeight;
    else {
        b -= Canvas.myHeight;
        if(b<0) b = -b;
    }
    //Calculate the x value
    if(x1>x2) x = x1 - (xPerF * animationFrame);
    else if(x1<x2) x = x1 + (xPerF * animationFrame);
    else x = x1;
    //Calculate the y value
    if(m!=0) y = (m * x + b) - Canvas.myHeight;
    else {
        if(y1>y2) y = y1 - (xPerF * animationFrame);
    else y = y1 + (xPerF * animationFrame);
    }
    g.fillOval((int) x - 15, (int) y - 15, 30, 30);
    //Debugging
    System.out.println("Frame " + animationFrame + " of " + animationSpeed + " | " + y + " = " + m + " * " + x + " + " + b + " | at speed of " + xPerF);

已更新

我希望动画在目标位置结束,但它总是过头或正好在目标位置。当目标相当笔直地位于塔上方时,它主要会过冲,给出或采用一些 x 坐标。我已经把它算作一个象限 1 x-y 平面,我相信我现在遇到的问题在于我如何计算斜率。谢谢!

已过时

这里有一个小程序来演示:https://drive.google.com/file/d/1fCTFJzulY1fcBUmdV6AXOd7Ol1g9B3lo/view?usp=sharing

点击每个目标进行定位

我认为您的方法存在根本性缺陷。它很容易出现舍入误差,这可能是超调的来源。在现实世界中也很难很好地工作,因为您的应用程序不是唯一的应用程序,因此 CPU 可能需求量很大,某些帧可能会被跳过,等等。更好的方法是使用时间而不是帧作为事件的主要驱动力。您的主要方法 drawScene 接受当前时间作为其参数之一。当任何动画开始时,您保存它开始的时间。然后,工作变得容易多了。例如对于线性动画,它将是这样的:

double animationPart = (currentTime - animationStartTime) / totalAnimationDuration;
// fix rounding error
if (animationPart > 1.0)
    animationPart = 1.0; 

double xCur = xStart * (1.0 - animationPart) + xEnd * animationPart;
double yCur = yStart * (1.0 - animationPart) + yEnd * animationPart;

P.S。 "time" 不一定是实时的,它可能是其他 "game time" 如果它在某种程度上更有意义,但恕我直言,这种方法更容易正确实施。


更新

我会说整体代码质量很差。关注点分离的很厉害,有很多magic numbers,还有全局静态的东西。例如,在这段代码中很难实现两颗子弹同时飞行。

动画代码中也有一些真正的错误。一些明显的错误是:

  1. xPerF计算错误。您划分欧几里得距离,而不仅仅是 X 坐标的差异。

  2. y 的逻辑有缺陷。至少你应该添加 m * (x - x1) 而不是 m * x。但它仍然不会涵盖垂直拍摄的情况(即 X 坐标根本没有改变的情况)。如果你想走这条路,你应该使用 xPerF yPerF 并摆脱 m 和相关的 if

这可能会或可能不会解决动画问题(在列表中您仍然有可能出现舍入错误)。我仍然会说将 shoot 更改为

public void shootTarget(int target) {
    shotTarget = target;
    shotTime = animationFrame;
}

然后使用

double animationPart = ((double) (animationFrame - shotTime)) / animationSpeed;

按照上面的建议是更好的方法。注意:这只是一个存根,因为在你的真实代码中,出于某种原因,你经常将 0 分配给 refresh,从而分配给 animationFrame,所以它不会那么容易工作。

回答

我明白了。我没有使用斜率截距法计算坐标,而是简单地计算了每帧必须递增 y 和 x 的间隔,并根据动画的帧递增它们。

double x, y, xPerF, yPerF; //Values for drawing
double x1, x2, y1, y2; //Values for the targets
x1 = getCenterX();
x2 = Canvas.target[shotTarget].getCenterX();
y1 = getCenterY();
y2 = Canvas.target[shotTarget].getCenterY();
xPerF = (Math.max(x1, x2) - Math.min(x1, x2))/animationSpeed;
yPerF = (Math.max(y1, y2) - Math.min(y1, y2))/animationSpeed;
if(x1>x2) x = x1 - xPerF * animationFrame;
else if(x1<x2) x = x1 + xPerF * animationFrame;
else x = x1;
if(y1>y2) y = y1 - yPerF * animationFrame;
else if(y1<y2) y = y1 + yPerF * animationFrame;
else y = y1;
g.fillOval((int) x - 15, (int) y - 15, 30, 30);