当禁用opengl和direct3d管道时(通过使用-Dsun.java2d.d3d=false和-Dsun.java2d.opengl=false调用vm),我无法找到任何使用Java2d进行平滑移动或动画的方法。
以下是简短且不太规范的代码,它演示了我的问题。 它绘制一个沿屏幕移动的方框。 方框位置每秒更新约60次,并尽可能多地重新绘制屏幕。 它使用BufferStrategy类实现双重缓冲; 翻转在“bs.show();”处完成。
代码(按Esc退出):
import java.awt.Color;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.Rectangle;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.image.BufferStrategy;
public class FluidMovement {
private static volatile boolean running = true;
private static final int WIDTH = 500;
private static final int HEIGHT = 350;
public static void main(String[] args) {
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsDevice gd = ge.getDefaultScreenDevice();
GraphicsConfiguration gc = gd.getDefaultConfiguration();
Frame frame = new Frame(gc);
frame.setIgnoreRepaint(true);
frame.setUndecorated(true);
frame.addKeyListener(new KeyAdapter() {
@Override public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_ESCAPE) {
running = false;
}
}
});
frame.setSize(WIDTH, HEIGHT);
frame.setVisible(true);
frame.createBufferStrategy(2);
BufferStrategy bs = frame.getBufferStrategy();
long nextTick = System.nanoTime();
class Rect {
int dx = 2, dy = 1, x = 0, y = 0;
}
Rect rect = new Rect();
Graphics g;
while (running) {
if (System.nanoTime() > nextTick) {
rect.x = (rect.x + rect.dx) % WIDTH;
rect.y = (rect.y + rect.dy) % HEIGHT;
nextTick += 1000000000 / 60;
}
g = bs.getDrawGraphics();
g.setColor(Color.BLACK);
g.fillRect(0, 0, WIDTH, HEIGHT);
g.setColor(Color.WHITE);
g.fillRect(rect.x, rect.y, 10, 10);
g.dispose();
bs.show();
}
bs.dispose();
frame.dispose();
}
}
当我使用"java FluidMovement"正常执行这段代码时,它运行得非常顺畅(除了偶尔的撕裂),因为jvm利用了direct3d/directdraw管道。但是当我使用"java -Dsun.java2d.d3d=false -Dsun.java2d.opengl=false FluidMovement"执行此代码时,它非常卡顿。
我不能假设直接使用direct3d或opengl管道。在我尝试过的3台计算机中,有2台计算机无法使用此管道;仅在运行Windows 7 的带有独立显卡的计算机上有效。是否有任何方法可以使方块平滑移动,还是应该使用像JOGL这样具有低级访问权限的库?
注:
- 帧率不是问题。在启用和禁用管道的两种情况下,应用程序都以超过300 fps的速度运行。在启用管道时,我强制关闭了垂直同步。
- 我已尝试了Toolkit.getDefaultToolkit().sync()
- 我已尝试了许多不同类型的循环,但移动永远不会真正流畅。即使是固定帧率,也会显示相同的卡顿。
- 我已尝试在全屏独占模式下运行框架。
- 我已尝试使用3甚至4个缓冲区。
Thread
和sleep
来维持帧率所需的时间。 - MadProgrammer