LibGDX 路径 (CatmullRomSpline) 恒速

2024-04-03

我试图使用 LibGDX CatmullRomSpline 在路径上实现恒定速度,但在使其正常工作时遇到问题。我已经尝试对这个主题进行了很多研究,包括阅读 LibGDX wiki,但他们对实现恒定速度的解释并没有真正意义,我无法让他们的方法发挥作用。就我而言,导数值非常大(数百个),因此当将 0-1 之间的数字除以导数时,结果非常小,并且移动非常慢并且仍然不恒定。所以我不确定他们的例子到底是如何工作的。

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

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

我对恒定速度的想法包括根据路径的总长度计算出速度(在样条曲线上使用 approxLength(1000) 方法),然后使用导数函数确定给定时刻的实际速度,并调整百分比值发送到样条曲线以补偿速度变化,从而使速度恒定。不过我不太明白导数函数到底代表什么。我之前发布了一个关于导数函数的问题,但根据我收到的评论,我认为询问实现恒定速度可能更容易。这是我之前关于导数函数的问题:LibGDX CatmullRomSpline 导数含义? https://stackoverflow.com/questions/32642338/libgdx-catmullromspline-derivative-meaning

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

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

这是我的示例代码:

桌面启动器.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;

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

迭代样条曲线以求导数 Average 的平均值:

 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;
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

LibGDX 路径 (CatmullRomSpline) 恒速 的相关文章

  • createImage(int width, int height) 的问题

    我有以下代码 作为游戏的一部分每 10 毫秒运行一次 private void gameRender if dbImage null createImage returns null if GraphicsEnvironment isHea
  • Java Runtime.getRuntime().freeMemory() 问题

    我搜索并看到了一些线程 但没有一个能够解决我遇到的具体问题 我正在尝试使用以下方式监视我的内存使用情况Runtime getRuntime freeMemory Runtime getRuntime maxMemory and Runtim
  • @RestController 没有 @ResponseBody 方法工作不正确

    我有以下控制器 RestController RequestMapping value base url public class MyController RequestMapping value child url method Req
  • 通过SOCKS代理连接Kafka

    我有一个在 AWS 上运行的 Kafka 集群 我想用标准连接到集群卡夫卡控制台消费者从我的应用程序服务器 应用程序服务器可以通过 SOCKS 代理访问互联网 无需身份验证 如何告诉 Kafka 客户端通过代理进行连接 我尝试了很多事情 包
  • 如何在 Firebase 远程配置中从 JSON 获取值

    我是 Android 应用开发和 Firebase 的新手 我想知道如何获取存储在 Firebase 远程配置中的 JSONArray 文件中的值 String 和 Int 我使用 Firebase Remote Config 的最终目标是
  • 使用 GWT 读取非常大的本地 XML 文件

    我正在使用 GWT 构建我的第一个 Java 应用程序 它必须从一个非常大的 XML 文件中读取数据 当我尝试发送对文件中信息的请求时遇到问题 并且我不太确定它是否与文件的大小或我的语义有关 在我的程序中 我有以下内容 static fin
  • org.hibernate.QueryException:无法解析属性:文件名

    我正在使用休眠Criteria从列中获取值filename在我的桌子上contaque recording log 但是当我得到结果时 它抛出异常 org hibernate QueryException 无法解析属性 文件名 com co
  • 使用 JUnit 时,有没有办法验证测试方法中是否调用了 try/catch 指令的 Catch 部分?

    例如 如果我想测试以下课程 public class SomeClass public void someMethod try Some code where comething could go wrong catch Exception
  • 如何使用 Hibernate (EntityManager) 或 JPA 调用 Oracle 函数或过程

    我有一个返回 sys refcursor 的 Oracle 函数 当我使用 Hibernate 调用该函数时 出现以下异常 Hibernate call my function org hibernate exception Generic
  • 在另一个模块中使用自定义 gradle 插件模块

    我正在开发一个自定义插件 我希望能够在稍后阶段将其部署到存储库 因此我为其创建了一个独立的模块 在对其进行任何正式的 TDD 之前 我想手动进行某些探索性测试 因此 我创建了一个使用给定插件的演示模块 到目前为止 我发现执行此操作的唯一方法
  • 了解joda时间PeriodFormatter

    我以为我明白了 但显然我不明白 你能帮我通过这些单元测试吗 Test public void second assertEquals 00 00 01 OurDateTimeFormatter format 1000 Test public
  • 内部存储的安全性如何?

    我需要的 对于 Android 我需要永久保存数据 但也能够编辑 并且显然是读取 它 用户不应访问此数据 它可以包含诸如高分之类的内容 用户不得对其进行编辑 我的问题 我会 并且已经 使用过Internal Storage 但我不确定它实际
  • HashMap 值需要不可变吗?

    我知道 HashMap 中的键需要是不可变的 或者至少确保它们的哈希码 hashCode 不会改变或与另一个具有不同状态的对象发生冲突 但是 HashMap中存储的值是否需要与上面相同 为什么或者为什么不 这个想法是能够改变值 例如在其上调
  • 在 SWT/JFace RCP 应用程序中填充巨大的表

    您将如何在 SWT 表中显示大量行 巨大是指超过 20K 行 20 列的东西 不要问我为什么需要展示那么多数据 这不是重点 关键是如何让它尽可能快地工作 这样最终用户就不会厌倦等待 每行显示某个对象的实例 列是其属性 一些 我想使用 JFa
  • java库维护数据库结构

    我的应用程序一直在开发 所以偶尔 当版本升级时 需要创建 更改 删除一些表 修改一些数据等 通常需要执行一些sql代码 是否有一个 Java 库可用于使我的数据库结构保持最新 通过分析类似 db structure version 信息并执
  • JMenu 中的文本居中

    好吧 我一直在网上寻找有关此问题的帮助 但我尝试的任何方法似乎都不起作用 我想让所有菜单文本都集中在菜单按钮上 当我使用setHorizontalTextPosition JMenu CENTER 没有变化 事实上 无论我使用什么常量 菜单
  • 是否可以使用 Java Guava 将函数应用于集合?

    我想使用 Guava 将函数应用于集合 地图等 基本上 我需要调整 a 的行和列的大小Table分别使所有行和列的大小相同 执行如下操作 Table
  • “无法实例化活动”错误

    我的一个 Android 应用程序拥有大约 100 000 个用户 每周大约 10 次 我会通过 Google 的市场工具向我报告以下异常情况 java lang RuntimeException Unable to instantiate
  • org.apache.commons.net.io.CopyStreamException:复制时捕获 IOException

    我正在尝试使用以下方法中的代码将在我的服务器中创建的一些文件复制到 FTP 但奇怪的是我随机地低于错误 我无法弄清楚发生了什么 Exception org apache commons net io CopyStreamException
  • Spring表单ModelAttribute字段验证避免400 Bad Request错误

    我有一个ArticleFormModel包含正常发送的数据html form由 Spring 使用注入 ModelAttribute注释 即 RequestMapping value edit method RequestMethod PO

随机推荐

  • android中处理html webview的onclick功能

    我正在尝试处理 android referred 中 html 的 onclick在此输入链接描述 https stackoverflow com questions 4065312 detect click on html button
  • iOS 中如何将代码块分派到同一个线程?

    问题的主要方面 这是关于 iOS 的 我能否以某种方式分派代码块 使它们全部 a 在后台运行并且 b 在同一个线程上运行 我想在后台运行一些耗时的操作 但这些操作必须在同一线程上运行 因为它们涉及资源 而不能在线程之间共享 如果需要 更多技
  • 在 ASP.NET Core 中,如何在Configure() 中使用在ConfigureServices() 中设置的服务?

    我编写了一项有助于配置的服务 该服务在 Startup 类的 ConfigureServices 方法中设置为 public void ConfigureServices IServiceCollection services servic
  • Java JComboBox 自动完成[关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • JSF 服务层

    我不确定我在 JSF 中使用 MVC 环境的方法是否是最好的方法 因为我试图充分利用 JSF 所以我想知道我的服务层 或模型 用 MVC 术语来说 应该如何 设计 我知道视图与控制器的比例应该是 1 比 1 排除例外 现在我应该以什么方式设
  • 从文件中 read() - 阻塞行为与非阻塞行为

    假设我们使用以下命令打开了一个文件fopen 并从收到的文件指针中 使用以下命令获取文件描述符fileno 然后我们做很多 gt 10 8 随机read 该文件中相对较小的块 大小在 4 字节到 10 KB 之间 这是预期的行为吗read
  • 测试有效输入 Python

    因此 我有一个完成的程序 它接受带有银行帐户信息的输入文件并对其进行解析并允许使用一些不同的实用程序 其中一个实用程序是将事务添加到 数据库 只是一个日志文件 程序提示用户输入 w 或 d 然后输入一个金额 浮点数 这代表存款或取款 X 金
  • Vstest.console.exe 找不到 nunit 测试

    我有 VS 2017 和 net 4 6 尝试使用 vstest console 通过 cmd 提示符运行时 vstest console exe bin Release Tests dll UseVsixExtensions true 我
  • 如何用css制作透明的羽毛首选项

    我想为一些图像添加羽毛 这是我想要最终得到的结果 我意识到这个问题之前已经发布过 并且我已经使用例如box shadow attr 但我对这个方法有一个问题 我要把这张照片放在webm 所以背景并不总是保持不变 这就是为什么我必须使羽毛透明
  • 如何将列表拆分为大小相等的块?

    如何将任意长度的列表拆分为大小相等的块 See also How to iterate over a list in chunks https stackoverflow com q 434287 To chunk strings see
  • 带 json 参数的 Curl GET 请求

    我正在尝试通过 cURL 从命令提示符向远程 REST API 发送 GET 请求 如下所示 curl X GET H Content type application json H Accept application json http
  • Flutter 如何将数据列表保存到本地存储

    我正在 flutter 上开发电影发现应用程序 我需要将正在播放的电影列表保存在本地存储上以供离线使用 那么我该怎么做 Future gt getNowPlayingMovies 异步 最终字符串现在正在播放 https api themo
  • 如何动态判断Objective-C属性类型?

    我正在尝试动态确定 Objective C 中属性的类型 根据我在本网站和其他地方读到的内容 我相信我正在做正确的事情 但是 我的代码不起作用 下面的代码片段演示了这个问题 尝试获取 backgroundColor 和 frame 的属性信
  • 使用 API 发布不包含图片、标题或元描述的链接 PHP

    使用 API 发帖时 我收到以下消息 https www facebook com weather warnings posts 329128793830700 https www facebook com weather warnings
  • EntityManager.createQuery() 抛出 NullPointerException

    每次都会遇到 NullPointerExceptionEntityManager createQuery or EntityManager createNamedQuery 叫做 我正在使用 Glassfish 4 0 Hibernate
  • 删除SQL Server中删除SQL文档后的弹出消息

    Goal 在 SQL Server 中移除 删除 SQL 文档时不显示弹出窗口 Problem 在我下载最新版本的 SQL Server 之前 当我删除 SQL 文档时 它没有显示任何有关状态的弹出窗口 当我下载最新版本的 SQL Serv
  • Django DateField 默认选项

    我有一个具有日期时间字段的模型 date models DateField Date default datetime now 当我在内置的 django admin 中检查应用程序时 DateField还附加了时间 因此如果您尝试保存它
  • 如何将联系人添加到 ActiveCampaign API v3 中的列表

    根据v3docs https developers activecampaign com v3 reference lists我应该能够使用联系人 API 将联系人添加到列表中 但我不知道如何执行此操作 因为我在下面看不到任何相关列表Con
  • 如何选择 PrimeFaces TreeTable 中的所有内容?

    我有一个 PrimeFaces 树表 想添加一个复选框 允许用户选择 取消选择全部 这是我的 xhtml 的摘录
  • LibGDX 路径 (CatmullRomSpline) 恒速

    我试图使用 LibGDX CatmullRomSpline 在路径上实现恒定速度 但在使其正常工作时遇到问题 我已经尝试对这个主题进行了很多研究 包括阅读 LibGDX wiki 但他们对实现恒定速度的解释并没有真正意义 我无法让他们的方法