java - 全屏帧率限制难题

标签 java swing awt fullscreen frame-rate

我的游戏(框架)在全屏模式下不能超过每秒 30 帧(更新调用之间大约 33 毫秒)。我在循环中使用定时器。实际上它变得有点复杂,因为当我逐渐减少延迟时,我测量的调用之间的时间变得疯狂。它从设置的延迟跳到预期值的两倍或更多。阈值似乎是 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();  
}

我回收了同一个 BufferedImage,因为制作新的 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;
}   

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

最佳答案

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

关于java - 全屏帧率限制难题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16124734/

相关文章:

java - 时间格式问题

java - 如何在 switch 语句中执行 actionPerformed?

java - ArrayList JTextField 空指针异常

java - 如果我知道列位置,请更改 JTable 中的列标题

java - 将文件读取到具有多种数据类型的数组列表

java - 如何在 Swing 中正确移动绘制的多边形

Java : Saving uploaded png image

java - 从 OpenPDF 获取溢出文本

java - Rest ,使用 Get 作为查询字符串发送参数或仅使用 Post 获取信息

java - 在 Guice 中避免框架强加的循环依赖