【问题标题】:Java graphics performanceJava 图形性能
【发布时间】:2009-12-12 13:37:45
【问题描述】:

我正在编写一个简单的游戏,并希望通过 Java Graphics + Swing API 来显示它。当然,感觉有点慢,所以我测量了重新绘制需要多长时间,大约是 32 毫秒。然后我阅读了有关加速 Java 图形的信息并使用了这里描述的方法:Space Invaders

但是,不知何故,这甚至更慢。现在重绘大约需要 98 毫秒。这是为什么呢?

请注意,我知道 LWGL 和 JOGL 之类的库,但我不想为这种图形简单的游戏使用成熟的 OpenGL 包装器。

【问题讨论】:

  • 你能发布一些你的绘画代码吗?和时钟/定时器逻辑?
  • 时钟/定时器逻辑只是通过 System.currentTimeMillis() 获得的两个 long 值的差。我知道这样测量时间不是一个好方法,但我只是想粗略估计一下需要多长时间。绘画代码只是将静态图像绘制到画布上。所以它只是 g.drawImage(img, 0, 0, null) 其中 g 是通过 BufferStrategy 变量获得的。

标签: java graphics


【解决方案1】:

提高性能的一些提示:

  1. 剪辑并仅绘制已更改的区域
  2. 绘图时不要缩放任何东西
  3. 使用正确的缓冲策略
  4. 如果合适,请使用full screen exclusive mode

Swing 本身并不慢。关于 Swing 的大部分困惑来自于不了解或不了解 Event Dispatch Thread 的人(是的,要做到这一点需要付出很多努力)。

关于你的时间,你只是在时间设置之间调用 g.drawImage 吗?如果是这样,您要重新绘制多大的尺寸,并且您是否在此调用中进行任何缩放?

编辑:忘了提到Pulp Core - 一个非常好的 Java 游戏框架。

【讨论】:

    【解决方案2】:
    1. 阅读this 了解定时器
    2. 在后台使用始终处于休眠状态的线程来降低系统中断率以获得更精确的计时器!
    3. 你可以看看我的代码here
    4. 我制作的一个小游戏可以找到here

      long renderStart = System.nanoTime()
      // render stuff here
      long renderTime = (System.nanoTime() - renderStart) / 1000000;
      

    【讨论】:

    • 我下载了你的图书馆(盆景)。但我有一个问题:你开了一门课GameEngine。这里的目的是什么(谷歌翻译)?
    • 其实我的 Eclipse SVN 插件有问题,所以它没有远程删除文件。就在今天,我通过另一个 SVN 客户端删除了该文件...这使整个 eclipse 项目崩溃,所以我不得不重建它,然后又以某种方式破坏了存储库:D 所以该文件只是开发的遗留物,有时我想要从 applet/gui 中提取出实际的引擎。
    【解决方案3】:

    在比赛中挥杆会很慢。您最好的选择可能是 SDL 包装器,例如 jsdlsdljava。 SDL 非常轻量级,并且在许多平台上都受支持。

    好消息是,良好实现的 2d 图形库包装器实现了Graphics 接口,因此您应该能够尝试多种,看看哪一种最适合您的应用程序,而无需修改您的代码。

    【讨论】:

    • 现在 jsdl 和 sdljava 都非常缺乏数据。大多数在 Java 上寻求高图形性能的人只是直接使用 OpenGL,例如通过 LWJGL (lwjgl.org)
    【解决方案4】:

    我不是专家,但 Java2D 支持不同的渲染管道。在我的机器上,通过设置系统属性切换到 OpenGL 一个

    sun.java2d.opengl=true

    显着提高了渲染速度。

    【讨论】:

      【解决方案5】:

      你可以看看processing

      【讨论】:

        【解决方案6】:

        我同意 Nicolas 的观点,因为图形/交互处理很棒

        【讨论】:

          【解决方案7】:

          试试JGame。这是一个用于 2D 游戏的简单引擎,它在可用时使用 GL,并且可以生成可在从手机到桌面系统的任何设备上运行的游戏。

          【讨论】:

            【解决方案8】:

            首先,您应该检查在您自己的代码中花费了多少时间与实际绘制框架花费了多少时间。您可能有一些错误或故障,使其运行更慢。

            您应该能够获得比 98 毫秒更好的性能来绘制屏幕。这些游戏库可能会使用与您相同的图形调用。但是,您使用哪些容器会对绘制速度产生重大影响。我记得几个月前在处理一些双缓冲图形代码时,后台缓冲区的创建方式对性能产生了巨大影响。

            特别是,确保只创建一次背景图像,或者至少只在画布调整大小时创建。在我的绘图代码中,我这样做:

                    //create a graphics backplane
                if(backplane == null || !backplaneSize.equals(this.getSize())){
                    backplane = this.createImage((int)this.getSize().getWidth(), (int)this.getSize().getHeight());
                    backplaneSize = this.getSize();
                }
            

            因此,只有当它是新的或调整组件大小时才会创建背板。这对速度有巨大的影响。

            自 JDK 1.0 以来,我一直在使用 java 进行图形编程。实际上我从来没有听说过这个 BufferStrategy 的事情。呵呵。

            我从来没有遇到过使用基本 java 图形调用获得良好帧速率的任何问题。要注意的另一件事是确保 Swing 不会试图为您清除组件的背景。这可能是另一个放缓的原因。

            【讨论】:

              【解决方案9】:

              Java2D 性能有点像一门黑暗的艺术。它可能因平台而异,但可以使其表现良好。

              有时做看似无害的事情可能会导致性能下降很多。你要确保你是using accelerated images as much as possible

              图片的type 也很重要。我不知道全部细节,但我知道由于转换问题,我的程序使用类型 1 图像 (INT RGB) 比使用类型 5 (3BYTE BGR) 等其他类型的图像要快得多。

              【讨论】:

                【解决方案10】:

                我不能确切地知道你在做什么。您的问题是关于 Swing,但您提到了 Canvas 和 Bufferstrategy。好吧,在 Swing 中,您将使用自动双缓冲的 JPanel,因此您不必担心。

                我测试了一个包含 1000 个移动球的简单动画。定时器设置为每 100 毫秒触发一次。当 Timer 触发时,随机移动到新位置的 1000 球创建了新的 BufferedImage,并重新绘制了显示图像的面板。重新绘制之间的时间差为 110 毫秒,这意味着创建一个新的 BufferedImage 并进行绘制只需要 10 毫秒。这幅画是全屏完成的,所以没有剪辑。

                这个posting 显示了我测试的示例代码。

                【讨论】:

                • 如果您想快速测量时间,最好的方法是使用 System.nanoTime()(JDK 1.5 中添加),它以纳秒为单位。它在长时间内不如 System.currentTimeMillis 准确,但在短期内它显然更有效。
                猜你喜欢
                • 2015-02-23
                • 2011-11-10
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多