全屏帧率限制难题

时间:2013-04-20 20:14:28

标签: java swing awt fullscreen frame-rate

我的游戏(框架)在全屏幕上的速度不能超过每秒30帧(更新呼叫之间大约33毫秒)。我使用Timer作为循环。实际上它变得有点复杂,因为当我逐渐减少延迟时,我测量的呼叫之间的时间变得疯狂。它从设定的延迟跳到预期值的两倍或更多。阈值似乎是30毫秒。在窗口模式下没有问题,其中差异开始出现在4 ms阈值处。两种模式通常在较高延迟时起作用。以下是我认为相关的部分代码。

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

以上是定时器设置。其余部分如下。

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

这是我的图形(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();  
}

我循环使用相同的BufferedImage,因为新的(与Graphics对象一起)使得一个内存泄漏。不知道是否使用相同的Graphics对象而不是每帧都执行.dispose()/ new Graphics。

在窗口模式下,BufferedImage在jFrame.getGraphics()和fulls-creen上绘制 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;
}   

知道为什么模式的不同行为? (除了帧速率和一些潜在的内存泄漏,程序运行顺利。)

1 个答案:

答案 0 :(得分:1)

理论上,计时器的周期不能短于渲染一帧所用的时间。实际上,它需要更长时间,否则您将立即使计时器的共享线程饱和。您需要profile才能确定。即使没有缩放,对drawImage()的呼叫通常也占主导地位。此AnimationTest显示最近几个FRAMES的渲染时间的移动平均值。您可以使用该方法调整实施以适应最慢的可接受目标平台。