2

我的游戏(框架)在全屏时不能超过每秒 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);     
}

这是我的 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,因为制作新的(连同 Graphics 对象)造成了内存泄漏。不知道是否使用相同的 Graphics 对象而不是每帧执行 .dispose() / new Graphics。

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

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

于 2013-04-21T03:07:47.610 回答