当禁用opengl和direct3d管道时(通过使用-Dsun.java2d.d3d = false和-Dsun.java2d.opengl调用vm),我无法找到使用Java2d进行任何平滑移动或动画的方法= FALSE)
下面的快速和脏代码演示了我的问题。它绘制了一个在屏幕上移动的框。盒子位置每秒更新大约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这样的低级访问库?
注意:
答案 0 :(得分:2)
有些事情在我身上跳了出来吓唬我......
我尝试了一些解决方案。
虽然我没有"重要的"问题,这些都是非常简单的例子,我通常使用默认的JVM选项获得更好的性能。
这基本上就是你所拥有的,开始对EDT很好并使用你正在使用的缓冲策略
public class SimpleAnimationTest {
private boolean running = true;
private Rectangle box = new Rectangle(0, 90, 10, 10);
private int dx = 4;
protected static final int WIDTH = 200;
protected static final int HEIGHT = 200;
public static void main(String[] args) {
new SimpleAnimationTest();
}
public SimpleAnimationTest() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame();
frame.setIgnoreRepaint(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.setSize(WIDTH, HEIGHT);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
frame.createBufferStrategy(2);
final BufferStrategy bs = frame.getBufferStrategy();
new Thread(new Runnable() {
@Override
public void run() {
long tock = 1000 / 60;
while (running) {
box.x += dx;
if (box.x + box.width > WIDTH) {
box.x = WIDTH - box.width;
dx *= -1;
} else if (box.x < 0) {
box.x = 0;
dx *= -1;
}
Graphics2D g = (Graphics2D) bs.getDrawGraphics();
g.setColor(Color.BLACK);
g.fillRect(0, 0, WIDTH, HEIGHT);
g.setColor(Color.WHITE);
g.fill(box);
g.dispose();
bs.show();
try {
Thread.sleep(tock);
} catch (InterruptedException ex) {
}
}
bs.dispose();
}
}).start();
}
});
}
}
public class SimpleAnimationTest {
private Rectangle box = new Rectangle(0, 90, 10, 10);
private int dx = 4;
public static void main(String[] args) {
new SimpleAnimationTest();
}
public SimpleAnimationTest() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new SimplePane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class SimplePane extends JPanel {
public SimplePane() {
setDoubleBuffered(true);
Timer timer = new Timer(1000 / 300, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
box.x += dx;
if (box.x + box.width > getWidth()) {
box.x = getWidth() - box.width;
dx *= -1;
} else if (box.x < 0) {
box.x = 0;
dx *= -1;
}
repaint();
}
});
timer.setRepeats(true);
timer.setCoalesce(true);
timer.start();
}
@Override
protected void paintComponent(Graphics g) {
Graphics2D g2d = (Graphics2D) g.create();
super.paintComponent(g2d);
box.y = (getHeight() - box.height) / 2;
g2d.setColor(Color.RED);
g2d.fill(box);
g2d.dispose();
}
@Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
}
}
答案 1 :(得分:0)
我已经通过切换到JOGL解决了我的问题。现在,在我之前遇到困难的机器上,一切都很顺利。
LWJGL也看起来很有前途,它让你几乎以与在C中相同的方式使用opengl。
如果其中一个管道工作,Java2D就很棒,但是它不是很可靠。我有幸在SDL中使用纯软件表面而不是java2d。