当禁用 opengl 和 direct3d 管道时(通过使用 -Dsun.java2d.d3d=false 和 -Dsun.java2d.opengl=false 调用 vm),我无法找到使用 Java2d 获得平滑移动或动画的方法
下面快速而肮脏的代码演示了我的问题。它绘制了一个在屏幕上移动的框。方框位置每秒更新大约 60 次,屏幕重绘尽可能多的次数。它使用 BufferStrategy 类来实现双缓冲;翻转在“bs.show();”完成
代码(按退出键退出):
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。启用管道时,我强制关闭 vsync。
- 我试过 Toolkit.getDefaultToolkit().sync()
- 我尝试了许多不同类型的循环,但运动从来都不是真正流畅的。即使使用固定的帧速率,也会表现出相同的断断续续。
- 我试过以全屏独占模式运行框架。
- 我尝试过使用 3 个甚至 4 个缓冲区。