2

私のゲーム (フレームワーク) は、全画面表示で毎秒 30 フレーム (更新呼び出し間で約 33 ミリ秒) よりも速くなりません。ループにはタイマーを使用します。実際にはもう少し複雑になります。遅延を段階的に減らすと、測定する呼び出し間の時間が狂ってしまうからです。設定された遅延から期待値の 2 倍以上にジャンプします。しきい値は 30 ミリ秒のようです。不一致が 4 ミリ秒のしきい値で現れ始めるウィンドウ モードでは問題ありません。どちらのモードも、より高い遅延で正常に動作します。以下は、関連すると思われるコードの一部です。

fps = 30;       
timer = new Timer(1000/fps, new ActionListener() {          
@Override
public void actionPerformed(ActionEvent arg0) {
    tick();             
}

以上がタイマーの設定です。以下は残りです。

private void tick(){
    update(gameTime);
    draw(gameTime);     
}

これが私のGraphics(2D)とBufferedImageです。

    public DrawBatch(DeviceManager deviceManager) {
    this.deviceManager = deviceManager;
    color = Color.MAGENTA;
    bufferedImage = deviceManager.getBufferedImage();       
    bufferedGraphics = (Graphics2D)bufferedImage.getGraphics();bufferedGraphics = (Graphics2D)bufferedImage.getGraphics();
    bufferedGraphics.setBackground(color);
    bufferedGraphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
    bufferedGraphics.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
    bufferedGraphics.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE); 
}

draw(GameTime gameTime) メソッドは、次のメソッドで始まります。

    public void begin(){
    bufferedGraphics.clearRect(0, 0, bufferedImage.getWidth(), bufferedImage.getHeight());  
}

これで、bufferedGraphics を使用して描画できます。draw(GT gT) はこれで終了。 (xna に触発)

    public void end(){
    if(deviceManager.isFullScreen())deviceManager.getGraphics().drawImage(bufferedImage, 0,0, null);
    else deviceManager.getGraphics().drawImage(bufferedImage, 3,25, null);      
    deviceManager.getGraphics().dispose();      
    bufferedImage.flush();  
}

新しいものを(Graphicsオブジェクトとともに)作成すると、メモリリークが発生したため、同じBufferedImageをリサイクルします。フレームごとに .dispose() / new Graphics を実行する代わりに、同じ Graphics オブジェクトを使用するかどうかはわかりません。

ウィンドウ モードでは、BufferedImage は jFrame.getGraphics() で描画され、フルスクリーンでは graphicDevice.getFullScreenWindow().getGraphics() で描画されます。

全画面設定はこちら。

public void setFS(){
    jFrame.setVisible(false);
    jFrame.dispose();
    jFrame.setIgnoreRepaint(true);
    jFrame.setResizable(false);
    jFrame.setUndecorated(true);
    graphicDevice.setFullScreenWindow(jFrame);
    graphicDevice.getFullScreenWindow().setIgnoreRepaint(true);
    graphicDevice.setDisplayMode(new DisplayMode(width, height, 32, 60));   
    jFrame.setVisible(true);        
    fullScreen = true;      
}

そしてウィンドウ設定。

public void setW(){
    jFrame.setVisible(false);
    jFrame.dispose();   
    jFrame.setIgnoreRepaint(true);
    jFrame.setResizable(false);
    jFrame.setUndecorated(false);
    graphicDevice.setFullScreenWindow(null);
    jFrame.setSize(width, height);      
    jFrame.setVisible(true);
    jFrame.getContentPane().setPreferredSize(new Dimension(800, 600));          
    jFrame.pack();      
    fullScreen = false;
}   

モードの異なる動作の理由は何ですか? (フレーム レートと潜在的なメモリ リークを除いて、プログラムはスムーズに実行されます。)

4

1 に答える 1

1

理論的には、タイマーの期間は、1 フレームのレンダリングにかかる​​時間より短くすることはできません。実際には、もっと長くする必要があります。そうしないと、タイマーの共有スレッドがすぐに飽和状態になります。確認するには、プロファイルを作成する必要があります。drawImage()スケーリングなしでも、通常は支配的な呼び出し。これAnimationTestは、過去数年間のレンダリング時間の移動平均を表示しますFRAMES。このアプローチを使用して、許容できる最も遅いターゲット プラットフォームに合わせて実装を調整できます。

于 2013-04-21T03:07:47.610 に答える