【问题标题】:JavaFX Simulating Carnot EngineJavaFX 模拟卡诺引擎
【发布时间】:2014-03-01 01:24:04
【问题描述】:

我正在寻找一些关于使用 JavaFX 以某种方式构建复杂动画的答案。 我正在尝试构建一个带有活塞移动等的简单卡诺引擎动画。 类似于this one

我需要的是开始编写此类模拟的最佳方式。 现在我熟悉 FX 中的 3 种模拟类型,因此我认为最好的选择是我的情况下的时间线模拟。

但我仍然不太确定如何开始。我是否应该在窗格上放置不同的砖块,如矩形、路径、圆圈,甚至不接触模拟并尝试将生命放入其中,或者这种方法完全是误解?这是我期待得到一些答案或至少是提示的问题。

【问题讨论】:

    标签: javafx simulation physics


    【解决方案1】:

    我会从一个物理引擎类开始,然后只输出文本。

    获取绘图中每个关键点的坐标,例如连接点和枢轴点,并使用真实的物理学计算它在接下来的 1/60 秒内应该在哪里。将这些位置与热变量等一起输出到控制台。确保它是正确的,然后用真实的形状和动画填充。 Javafx 使用 60 帧/秒的标准。

    如果绘图是 2d 并且模拟是 3d(现实世界)物理,则在两者之间转换可能会遇到一些麻烦。对于奖励积分,您可以进行 3d 模拟。

    【讨论】:

    • 是的,这是一个不错的建议。在此之后,我现在正在为自己准备一些理论背景,在我最终获得能够计算卡诺循环相关内容的层之后,我将开始使用动画。然而,我对这个问题的关注不是物理而是动画本身。我想在设计模拟时获得一些重要检查点的提示。例如,是独立制作引擎的每个组件还是与其他组件一起制作动画?我应该用什么来控制动画?活塞的当前位置,时间?
    • This will get you started 针对特定动画问题提出新问题。这个问题可能是这个板的边界 OT。
    【解决方案2】:

    嗯...当涉及到 Javafx 时,我也对模拟器和游戏感兴趣

    几个月前我创建了一个布料模拟器,虽然它并不完美,但它是我的第一个全新模拟器。

    你可以期待的问题:

    更新UI,所有节点都必须在FXthread上更新 在不影响场景性能的情况下运行更新

    AnimationTimer 是最好的解决方案。使用标准动画会创建一堆代码。

    我的解决方案是创建一个每 16 毫秒运行一次的 LoopService (ScheduledService) (大约 60 fps)仅此一项就几乎使我的性能与 AnimationTimer 相比翻了一番。

    LoopService 的好处在于您可以让代码在 fxthread 之外运行,并且 onSucceeded 更新 UI 而无需额外的侦听器等。

    这是最终结果的 youtube 视频:https://www.youtube.com/watch?v=uRsCcpbsdsg (出于某种原因,该视频已上传到旧帐户)

    您可以在我的实际 youtube 页面上查看进度:
    https://www.youtube.com/channel/UCxCaGZeistOC2J_rBF8JbWQ

    我的数学远非完美,还需要大量改进,但我涵盖了更新 UI 的困难部分。 在源代码中,我用不同的名称调用服务,但基础是相同的。

    布料的源代码在这里:https://github.com/Birdasaur/FXyz 在 Tests 文件夹中,您应该会找到一个可运行的示例。

    希望对您有所帮助!

    这是该服务的更新版本:

    /**
     * Simple Looping Service. Useful for games, Simulations, or other items that require a running "Loop".
     *
     * @author Jason Pollastrini aka jdub1581
     */
    public abstract class AbstractLoopService extends ScheduledService<Void>{
        private final long ONE_NANO = 1_000_000_000L;
        private final double ONE_NANO_INV = 1f / 1_000_000_000L;
    
        private long startTime, previousTime;
        private double frameRate, deltaTime;
    
        private final LoopThreadFactory tf = new LoopThreadFactory();    
        private final ExecutorService cachedExecutor = Executors.newCachedThreadPool(tf);
    
    
        protected AbstractLoopService() {
            this.setPeriod(Duration.millis(16.667)); // eqiv to 60 fps
            this.setExecutor(cachedExecutor);
        }
    
    
        protected final double getTimeElapsed() {
            return getCurrentTime() * ONE_NANO_INV;
        }
    
        protected final long getCurrentTime() {
            return System.nanoTime() - startTime;
        }
    
        protected final double getFrameRate() {
            return frameRate;
        }
    
        protected final double getDeltaTime() {
            return deltaTime;
        }
    
        private void updateTimer() {
            deltaTime = (getCurrentTime() - previousTime) * (1.0f / ONE_NANO);
            frameRate = 1.0f / deltaTime;
            previousTime = getCurrentTime();
    
        }
    
        @Override
        public void start() {
            super.start();
            if (startTime <= 0) {
                startTime = System.nanoTime();
            }
        }
    
        @Override
        public void reset() {
            super.reset();
            startTime = System.nanoTime();
            previousTime = getCurrentTime();
        }
    
        @Override
        protected Task<Void> createTask() {
            return new Task<Void>() {
                @Override
                protected Void call() throws Exception {
                    updateTimer();
                    // perform needed background tasks here ..
                    runInBackground();
    
                    return null;
                }
            };
        }
    
        @Override
        protected void succeeded() {
            super.succeeded();
            // Setup to handle Actions for UI here     
            runOnFXThread();
        }
    
        @Override
        protected void failed() {
            getException().printStackTrace(System.err);
    
        }
    
        @Override
        public String toString() {
            return "ElapsedTime: " + getCurrentTime() + "\nTime in seconds: " + getTimeElapsed()
                    + "\nFrame Rate: " + getFrameRate()
                    + "\nDeltaTime: " + getDeltaTime();
        }
    
        /*==========================================================================
         *      Methods for access
         */
    
        protected abstract void runOnFXThread();
        protected abstract void runInBackground();
    
        /*==========================================================================
    
         */
        private final class LoopThreadFactory implements ThreadFactory {
    
            public LoopThreadFactory() {
            }
    
            @Override
            public Thread newThread(Runnable r) {
                Thread t = new Thread(r, "NanoTimerThread");
                t.setPriority(Thread.NORM_PRIORITY + 1);
                t.setDaemon(true);
                return t;
            }
    
        }
    
    }
    

    【讨论】:

      猜你喜欢
      • 2019-04-01
      • 2010-12-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-06-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多