簡體   English   中英

全屏幀率限制難題

[英]Full-screen frame-rate limit conundrum

我的游戲(框架)在全屏狀態下的運行速度不能超過每秒30幀(兩次更新調用之間約33毫秒)。 我使用一個計時器循環。 實際上,它變得有點復雜,因為當我逐漸減少延遲時,我測量的兩次呼叫之間的時間就變得很瘋狂。 它從設置的延遲跳到期望值的兩倍或更多。 該閾值似乎是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()上,而全畫幅繪制在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;
}   

知道為什么模式的行為不同嗎? (除了幀速率和一些潛在的內存泄漏,該程序運行平穩。)

從理論上講,計時器的周期不能短於渲染一幀所花費的時間。 實際上,它需要更長的時間,否則您將立即飽和計時器的共享線程。 您需要進行個人資料確定。 即使沒有縮放比例,對drawImage()調用通常仍占主導地位。 AnimationTest顯示最后幾個FRAMES的渲染時間的移動平均值。 您可以使用該方法來調整實現,以適應最慢的可接受目標平台。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM