Java图形性能

6
我正在编写一个简单的游戏,并希望通过Java Graphics + Swing API来显示它。当然,感觉有点慢,所以我测量了重绘所需的时间,大约是32毫秒。然后我了解到了加速Java图形的方法,并使用了这里描述的方法:Space Invaders
然而,不知何故,这样做甚至更慢了。现在需要约98毫秒才能重新绘制。为什么会这样呢?
请注意,我知道像LWGL和JOGL这样的库,但是我不想为这样一个图形简单的游戏使用完整的OpenGL封装。

1
你能发布一些你的绘画代码和时钟/计时器逻辑吗? - basszero
时钟/计时器逻辑就是通过System.currentTimeMillis()获取的两个长整型值之差。我知道这不是一个好的测量时间的方法,但我只想大致估计需要多长时间。绘图代码只是将静态图像绘制到画布上。所以它只是g.drawImage(img, 0, 0, null),其中g是通过BufferStrategy变量获取的。 - Marc Müller
10个回答

7
一些提高性能的提示:
  1. 裁剪并仅绘制更改的区域
  2. 绘制时不要进行缩放
  3. 使用正确的缓冲策略
  4. 如果适合,使用全屏独占模式
Swing本质上并不慢。大多数有关Swing的困惑来自于不了解或不理解事件分派线程的人(是的,要做对它需要付出很多努力)。
关于您的时间,您只是在时间设置之间调用g.drawImage吗?如果是这样,您正在重绘什么大小的内容,并且是否在此调用中进行了任何缩放? 编辑:忘记提到Pulp Core - 一个非常好的Java游戏框架。

6
  1. Read this about timers
  2. Use an always sleeping thread in the background to lower the system interrupt rate to get much more precise timers!
  3. You can take a look at my code in here
  4. A small game I've created can be found here

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

我下载了你的库(Bonsai)。但我有一个问题:你创建了一个名为 GameEngine 的类。这里的目的是什么? - Martijn Courteaux
实际上,我在使用Eclipse SVN插件时遇到了问题,它没有远程删除文件。就在今天,我通过另一个SVN客户端删除了该文件……这导致整个Eclipse项目崩溃,因此我不得不重新构建它,然后又以某种方式破坏了存储库:D 所以该文件只是开发中留下的残留物,曾经想将实际引擎从小程序/ GUI中分离出来。 - Ivo Wetzel

6
Swing在游戏中会很慢。您最好选择SDL包装器,例如jsdlsdljava。SDL非常轻量级,并支持许多平台。
不错的是,实现良好的2D图形库包装器实现了Graphics接口,因此您应该能够尝试几个并查看哪个对您的应用程序执行效果最佳,而无需修改代码。

现在,jsdl和sdljava都已经非常过时了。大多数寻求Java高性能图形的人直接使用OpenGL,例如通过LWJGL(http://lwjgl.org/)。 - mikera

3

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

sun.java2d.opengl=true

切换到OpenGL管道可以显著提高渲染速度。


2

1
首先,您应该检查并查看自己的代码花费了多少时间,而实际上绘制帧花费了多少时间。您可能会遇到一些错误或故障导致其运行变慢。
您应该能够获得比98ms更好的性能来绘制屏幕。这些游戏库可能会使用与您相同的图形调用。但是您使用哪些容器可能会对绘制速度产生很大影响。我记得几个月前在某些双缓冲图形代码上工作时,背景缓冲区的创建方式对性能有很大影响。
特别是,请确保您仅在画布调整大小时创建背景图像,或者至少仅创建一次。在我的绘制代码中,我这样做:
        //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不会尝试为您清除组件的背景。那也可能是减速的另一个来源。


1

我同意Nicolas的观点,对于图形/交互处理来说非常棒。


1

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


1

Java2D的性能有点玄学。它在不同平台上的表现可能会有所不同,但是可以通过优化来提高其性能。

有时候看似无害的操作也可能导致性能变慢。您需要确保尽可能地使用加速图像

图像类型也很重要。我不知道所有细节,但我知道我的程序使用类型1图像(INT RGB)比其他类型(如类型5(3BYTE BGR))快得多,因为避免了转换问题。


1

我无法确定你在做什么。你的问题涉及Swing,但你提到了Canvas和Bufferstrategy。在Swing中,你应该使用JPanel,它自动双缓冲,所以你不必担心这个。

我测试了一个简单的动画,有1000个移动的球。计时器设置为每100毫秒触发一次。当计时器触发时,1000个球会随机移动到新位置,并创建一个新的BufferedImage,然后重新绘制显示图像的面板。重新绘制之间的时间差为110ms,意味着只需要10ms来创建新的BufferedImage并进行绘制。绘制是在全屏幕上完成的,因此没有剪辑。

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


如果您想要测量某个快速操作所需的时间,最好的方法是使用System.nanoTime()(自JDK1.5开始提供),它以纳秒为单位进行计量。与System.currentTimeMillis相比,它在长时间内可能不如后者准确,但对于短时间来说显然更加高效。 - Chad Okere

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接