gpt4 book ai didi

java - LibGDX 路径 (CatmullRomSpline) 恒速

转载 作者:搜寻专家 更新时间:2023-11-01 02:06:08 24 4
gpt4 key购买 nike

我正在尝试使用 LibGDX CatmullRomSpline 在一条路径上实现恒定速度,但我在让它工作时遇到了问题。我已经尝试过很多关于这个主题的研究,包括阅读 LibGDX wiki,但他们对实现恒定速度的解释并没有真正意义,我无法让他们的方法起作用。 https://github.com/libgdx/libgdx/wiki/Path-interface-&-Splines在我的例子中,微分值非常大(以数百计),因此当将 0-1 之间的数字除以微分时,结果非常小并且移动非常缓慢且仍然不稳定。所以我不确定他们的示例究竟是如何工作的。

在我的例子中,我有几个视觉辅助工具与球的速度相吻合,屏幕底部的条随着速度的增加而增加长度,并且颜色也随着速度的增加从白色变为红色。

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

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

任何有关如何在我的示例中实现恒定速度的想法(或解释 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);
}
}

测试.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<Vector2> 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<Vector2>(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);
}
}
}

最佳答案

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

您没有获得恒定的速度,因为您仍在按增量而不是增量除以变化率(导数)来增加时间变量。您应该在每帧的百分比变量中添加一个变量,而不是通过沿 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;

关于java - LibGDX 路径 (CatmullRomSpline) 恒速,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32665262/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com