LibGDX路径(CatmullRomSpline)恒速

我正在尝试使用LibGDX CatmullRomSpline在路径上实现恒定速度,并且我在使其工作时遇到问题。 我已经尝试过很多关于这个主题的研究,包括阅读LibGDX维基,但他们对实现恒定速度的解释并没有真正意义,我无法让他们的方法发挥作用。 https://github.com/libgdx/libgdx/wiki/Path-interface-&-Splines在我的例子中,导数值非常大(数百),所以当将0到0之间的数除以导数时非常小,运动非常慢,但仍然不恒定。 所以我不确定他们的例子是如何运作的。

在我的例子中,我有几个视觉辅助工具与球的速度一致,随着速度的增加,屏幕底部的条形长度增加,随着速度的增加,颜色也会从白色变为红色。

在MyPath.java的act()方法中,我从[1]和[2]开始注释掉了两个部分。 第一个是正常的,通过路径可变速度,第二个是我尝试使LibGDX wiki恒速工作失败。 所以只需取消注释这两行就可以在两个版本之间切换。

我对恒速的想法包括根据路径的总长度计算速度(使用样条上的约长度(1000)方法),然后使用导数函数确定给定时刻的实际速度,并调整百分比发送到样条曲线的值以补偿速度变化,以使速度恒定。 但是,我不太明白衍生函数实际上代表什么。 我之前发布了关于衍生函数的问题,但根据我收到的评论,我认为可能更容易询问实现恒定速度。 这是我之前关于导数函数的问题: LibGDX CatmullRomSpline导数意义?

关于如何在我的例子中实现恒定速度的任何想法(或解释CatmullRomSpline的衍生函数实际上代表什么,以便我可以更好地理解如何使用它)将不胜感激。

对于任何想要运行该程序的人,这里是我为我的示例创建的两个图像文件(将这些文件添加到assets文件夹的根目录): http : //dropshots.com/Tekker/date/2015-09- 19

这是我的示例代码:

DesktopLauncher.java 🙁将桌面窗口宽度和高度更改为1000)

public class DesktopLauncher { public static void main (String[] arg) { LwjglApplicationConfiguration config = new LwjglApplicationConfiguration(); config.width = 1000; config.height = 1000; new LwjglApplication(new TEST(), config); } } 

TEST.java:

 public class TEST extends Game { Stage stage; MyPath path; @Override public void create () { stage = new Stage(); stage.setViewport(new ScreenViewport(stage.getViewport().getCamera())); Gdx.input.setInputProcessor(stage); path = new MyPath(1000, 1000); stage.addActor(path); } @Override public void render () { Gdx.gl.glClearColor(0.1f, 0.1f, 0.1f, 1.0f); Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT); stage.act(Gdx.graphics.getDeltaTime()); stage.draw(); } @Override public void dispose(){ stage.dispose(); super.dispose(); } } 

MyPath.java:

 public class MyPath extends WidgetGroup { Image start, end, path, bar1, horizontal; float time, percent, dVal, pathLength, dMax=1000, cycle=6, maxPercent, deltaCycle; CatmullRomSpline catmull; Vector2 result = new Vector2(); Vector2 previousResult = new Vector2(50,150); Vector2 derivative = new Vector2(); Vector2 previousDerivative = new Vector2(); Vector2[] points = { new Vector2(50,150), new Vector2(50,150), new Vector2(400,800), new Vector2(600,150), new Vector2(700,400), new Vector2(860,150), new Vector2(860,150) }; boolean print = true; public MyPath(int width, int height){ this.setSize(width, height); catmull = new CatmullRomSpline(points, false); createPath(); createBar(); pathLength = catmull.approxLength(1000); } @Override public void act(float delta){ // [1] VARIABLE SPEED //time += delta; //percent = (time / cycle) % 1; // [2] CONSTANT SPEED FAIL! //catmull.derivativeAt(previousDerivative, percent); //time += delta; //percent = ((time / cycle) / previousDerivative.len() ) % 1; catmull.valueAt(result, percent); path.setPosition(result.x, this.getHeight() - result.y); updateSpeedVisuals(); debugPrint(); previousResult.set(result); } private void createPath(){ start = new Image(new Texture("dot.png")); start.setColor(Color.GRAY); start.setPosition(50, this.getHeight() - 150); this.addActor(start); end = new Image(new Texture("dot.png")); end.setColor(Color.GRAY); end.setPosition(860, this.getHeight() - 150); this.addActor(end); path = new Image(new Texture("dot.png")); path.setColor(Color.WHITE); this.addActor(path); } private void createBar(){ Texture texture = new Texture("ninepatch.png"); int crop = (int)(texture.getWidth()/2)-1; NinePatch patch9 = new NinePatch(texture, crop, crop, crop, crop); bar1 = new Image(patch9); bar1.setColor(Color.GRAY); bar1.setPosition(5, this.getHeight()-900); this.addActor(bar1); } private void updateSpeedVisuals(){ catmull.derivativeAt(derivative, percent); dVal = derivative.len() / dMax; path.setColor(1f, 1f-dVal, 1f-dVal, 1f); bar1.setWidth(derivative.len()); bar1.setColor(1f, 1f-dVal, 1f-dVal, 1f); } private void debugPrint(){ maxPercent = (percent > maxPercent) ? percent : maxPercent; if (maxPercent > percent){ print = false; } if (print){ String debugPrint = ""; debugPrint = debugPrint + "pathLength=" + pathLength + "\t"; debugPrint = debugPrint + "derivative=" + derivative.len() + "\t"; System.out.println(debugPrint); } } } 

由于导数是样条位置的变化率,它确实是“速度”,当样条曲线远离基础数据点时,它必须“加速”以使计算的样条曲线到达下一个数据点。时间,你必须分出这个速度,以感知视觉恒定的速度。

你没有获得恒定的速度,因为你仍然用delta而不是delta除以变化率(导数)来增加你的时间变量。 您应该在每个帧的百分比变量中添加一个可变量,而不是通过沿Catmull-Rom样条曲线的单个点的导数修改所有内容。

代替:

 catmull.derivativeAt(previousDerivative, percent); time += delta; percent = ((time / cycle) / previousDerivative.len() ) % 1; 

你应该:

 catmull.derivativeAt(previousDerivative, percent); percent += derivativeAverage / cycle * delta / previousDerivative.len(); percent %= 1; 

你现在应该使用平均导数除以循环,因为你不能再单独使用循环作为每秒百分比变量。

迭代样条曲线以查找derivativeAverage的平均值:

  int samples = 100; //the higher the more accurate, however slower float derivativeAverage = 0; Vector2 out = new Vector2(); for (float i=0;i<1;i+=1f/samples) { catmull.derivativeAt(out, i); derivativeAverage += out.len(); } derivativeAverage /= samples;