简体   繁体   中英

Full-screen frame-rate limit conundrum

my game(framework) can't go faster than 30 frames per second(about 33 ms between update calls) in full-screen. I use a Timer for the loop. Actually it gets a bit more complicated, since when i decrease the delay incrementally, the time between calls i measure goes nuts. It jumps form the set delay to twice or more the expected value. The threshold seems to be 30 ms. No problem in windowed mode, where discrepancies start to appear at the 4 ms threshold. Both modes act normally at higher delays. Here are parts of the code that I think are pertinent.

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

Above is the Timer setup. Below is the rest.

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

Here is my Graphics(2D) and 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); 
}

The draw(GameTime gameTime) method begins with this method:

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

Now we can draw using bufferedGraphics. draw(GT gT) ends with this.(inspired by 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();  
}

I recycle the same BufferedImage since making new one(along with a Graphics object) made one hell of a memory leak. Don't know if using the same Graphics object instead of doing .dispose() / new Graphics every frame.

In windowed mode, the BufferedImage is drawn on jFrame.getGraphics() and in fulls-creen on graphicDevice.getFullScreenWindow().getGraphics().

Here is the full-screen setup.

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;      
}

And the windowed setup.

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;
}   

Any idea why the different behaviors of the modes? (Except for the frame-rate and some potential memory leaks, the program runs smoothly.)

Theoretically, the timer's period can be no shorter than the time taken to render one frame. Practically, it needs to be longer or you'll immediately saturate the timer's shared thread. You'll need to profile to be sure. Calls to drawImage() typically dominate, even without scaling. This AnimationTest displays a moving average of the render time over the last few FRAMES . You can use the approach to tune your implementation to suit your slowest acceptable target platform.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM