简体   繁体   English

LibGDX路径(CatmullRomSpline)恒速

[英]LibGDX Path (CatmullRomSpline) Constant Speed

I'm trying to achieve constant speed on a path using the LibGDX CatmullRomSpline and I'm having problems getting it to work. 我正在尝试使用LibGDX CatmullRomSpline在路径上实现恒定速度,并且我在使其工作时遇到问题。 I've tried researching on this topic a lot including reading the LibGDX wiki, but their explanation for achieving constant speed doesn't really make sense and I wasn't able to get their method to work. 我已经尝试过很多关于这个主题的研究,包括阅读LibGDX wiki,但他们对实现恒定速度的解释并没有真正意义,我无法让他们的方法发挥作用。 https://github.com/libgdx/libgdx/wiki/Path-interface-&-Splines In my case, the derivative values are very large (in the hundreds) so when dividing a number between 0-1 by the derivative the result is very small and the movement is very slow and still not constant. https://github.com/libgdx/libgdx/wiki/Path-interface-&-Splines在我的例子中,导数值非常大(数百),所以当将0-1之间的数除以导数时非常小,运动很慢,但仍然不恒定。 So I'm not sure exactly how their example works. 所以我不确定他们的例子是如何运作的。

In my example I have a couple visual aids coinciding with the speed of the ball, the bar at the bottom of the screen increases in length as the speed increases and the color also changes from white to red as the speed increases. 在我的例子中,我有几个视觉辅助工具与球的速度一致,随着速度的增加,屏幕底部的条形长度增加,随着速度的增加,颜色也会从白色变为红色。

In the act() method of MyPath.java I have two sections commented out starting with [1] and [2]. 在MyPath.java的act()方法中,我从[1]和[2]开始注释掉了两个部分。 The first one is normal with the variable speed through the path and the second one is my failed attempt at getting the LibGDX wiki constant speed to work. 第一个是正常的,通过路径可变速度,第二个是我尝试使LibGDX wiki恒速工作失败。 So just un-comment these lines to switch between the two versions. 所以只需取消注释这两行就可以在两个版本之间切换。

My idea for constant speed involves figuring out the speed based on the total length of the path (using the approxLength(1000) method on the spline), then using the derivative function to determine the actual speed at a given instant, and adjusting the percentage value sent into the spline to compensate for the speed changes in order to make the speed constant. 我对恒速的想法包括根据路径的总长度计算速度(使用样条上的约长度(1000)方法),然后使用导数函数确定给定时刻的实际速度,并调整百分比发送到样条曲线的值以补偿速度变化,以使速度恒定。 However, I don't quite understand what the derivative function actually represents. 但是,我不太明白衍生函数实际上代表什么。 I posted a question about the derivative function earlier, but based a comment I received I figured it might be easier to ask about achieving constant speed instead. 我之前发布了关于衍生函数的问题,但根据我收到的评论,我认为可能更容易询问实现恒定速度。 Here is my previous question on the derivative function: LibGDX CatmullRomSpline Derivative Meaning? 这是我之前关于导数函数的问题: LibGDX CatmullRomSpline导数意义?

Any ideas on how to achieve constant speed in my example (or explaining what the derivative function for the CatmullRomSpline actually represents so I could better understand how to use it) would be greatly appreciated. 关于如何在我的例子中实现恒定速度的任何想法(或解释CatmullRomSpline的衍生函数实际上代表什么,以便我可以更好地理解如何使用它)将不胜感激。

For anyone who'd like to run the program, here are the two image files I created for my example (add these to the root of the assets folder): http://dropshots.com/Tekker/date/2015-09-19 对于任何想要运行程序的人,这里是我为我的示例创建的两个图像文件(将这些文件添加到assets文件夹的根目录): http//dropshots.com/Tekker/date/2015-09- 19

Here is my example code: 这是我的示例代码:

DesktopLauncher.java: (changed desktop window width and height to 1000) 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: 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: 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);
        }
    }
}

Since the derivative is the rate of change of the spline position it is indeed the 'speed', and when the spline is bending away from the underlying data points it has to 'speed up' to make the calculated spline reach the next data point in time, you must divide out this speed to perceive a visual constant speed. 由于导数是样条位置的变化率,它确实是“速度”,当样条曲线远离基础数据点时,它必须“加速”以使计算的样条曲线到达下一个数据点。时间,你必须分出这个速度,以感知视觉恒定的速度。

You aren't getting a constant speed because you are still incrementing your time variable by delta instead of delta divided by the rate of change (derivative). 你没有得到一个恒定的速度,因为你仍然用delta而不是delta除以变化率(导数)来递增你的时间变量。 You should be adding a variable amount to the percent variable each frame, instead you were modifying everything by the derivative of a single point along the Catmull-Rom spline. 您应该在每个帧的百分比变量中添加一个可变量,而不是按照Catmull-Rom样条曲线上单个点的导数修改所有内容。

Instead of: 代替:

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

You should: 你应该:

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

you should use the average derivative divided by cycle now since you can't use cycle alone as a percent per second variable anymore. 你现在应该使用平均导数除以循环,因为你不能再单独使用循环作为每秒百分比变量。

Iterating over the spline to find the average value of the derivativeAverage: 迭代样条曲线以查找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;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM