opengl および direct3d パイプラインが無効になっている場合 (-Dsun.java2d.d3d=false および -Dsun.java2d.opengl=false で vm を呼び出すことにより)、Java2d を使用してスムーズな動きやアニメーションを取得する方法がわかりません。
以下の簡単で汚いコードは、私の問題を示しています。画面上を移動するボックスを描画します。ボックスの位置は 1 秒間に約 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 つのバッファーを使用してみました。