【问题标题】:How to calculate points on a line at intervals如何每隔一段时间计算一条线上的点
【发布时间】:2018-12-22 01:39:10
【问题描述】:

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

我一直在玩确定事物的斜率截距方法,并且我正在接近,但我被卡住了。

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

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

点击每个目标来定位它

【问题讨论】:

  • 也许你可以准备可重现的例子?
  • @Antoniossss 你什么意思?
  • 我的意思是创建一段我可以在本地实际运行的代码,也许可以尝试修复它。
  • 为什么要重新发明轮子?查看物理引擎,例如 box2d。
  • 我想复制粘贴然后运行看看效果。

标签: java math points


【解决方案1】:

我认为您的方法存在根本缺陷。它容易出现舍入误差,这可能是超调的来源。在您的应用程序不是唯一的应用程序的现实世界中也很难很好地工作,因此 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;

附: “时间”不一定是实时的,如果它以某种方式更有意义,它可能是其他一些“游戏时间”,但恕我直言,这种方法更容易正确实施。


更新

我会说整体代码质量相当糟糕。关注点严重分离,有很多magic numbers,还有全局静态的东西。例如,在这段代码中实现两颗子弹并不容易。

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

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

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

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

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

然后使用

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

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

【讨论】:

  • 感谢您的回复。不过我有几个问题;一、什么是totalAnimationDuration?二,现在和开始时间是什么时候?第三,什么是舍入误差?
  • 另外,我理解时间而不是帧的使用,但我程序中的其他所有内容都是基于帧的。因此,如果跳过一帧,结果实际上是程序似乎变慢了。将来我肯定会考虑使用时间,但我不希望重组我的整个代码以适应一个使用时间的函数。如果您可以发布与框架有关的内容,将不胜感激
  • 我实际上一直在研究这个并计算了一个 y 截距改变数学值来模拟 x-y 平面的象限 1。我将刷新分配为 0,因为对象射击是塔防游戏中的一座塔,它在刷新变量上运行。我正在编辑 OP 中给出的代码。
  • 另外,我想知道你所说的舍入误差是什么意思。 P.S.,动画变量只和射击相关,是根据塔本身的射击进度,以便在射击和伤害之间提供一致的视觉反馈。
【解决方案2】:

回答

我想通了。我没有使用斜率截距方法计算坐标,而是简单地计算了每帧增加 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);

【讨论】:

    猜你喜欢
    • 2018-08-03
    • 2011-03-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-10
    • 1970-01-01
    相关资源
    最近更新 更多