You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java游戏全屏模式运行FPS远低于窗口模式问题咨询

问题原因

帧率骤降核心是Swing渲染逻辑在全屏模式下触发了多个性能瓶颈,和游戏逻辑本身无关:

  • 直接调用getGraphics()获取组件图形对象绘制,完全绕开Swing的事件调度线程(EDT)和内置双缓冲机制。窗口模式下面板尺寸小,额外开销不明显,切到1080p全屏后,直接绘制+无调度的重绘会把CPU/显卡的无效开销拉满。
  • 离屏渲染用的BufferedImage始终是320240分辨率,全屏下每次绘制都要把这张小图拉伸到1080p,默认走CPU软件缩放,渲染面积是640480窗口模式的9倍,性能开销陡增。
  • 切全屏时没有关闭窗口装饰、没有匹配屏幕显示模式,系统桌面合成器(比如Windows的DWM)会持续对窗口做合成处理,不仅会额外消耗性能,还可能被垂直同步强制锁帧。
  • 每次渲染后直接dispose()和屏幕表面绑定的Graphics对象,频繁销毁重建图形上下文会带来不必要的开销。
修复方案

按以下步骤修改即可恢复全屏下的高帧率:

  1. 放弃直接调用getGraphics()绘制的写法,全屏模式下用BufferStrategy做页翻转渲染,这是Java全屏独占模式下性能最高的渲染路径,可以直接绕过桌面合成器的额外处理。
  2. 切全屏时主动关闭窗口边框,匹配屏幕原生分辨率,不要硬编码固定尺寸。
  3. 给图形上下文设置最快的缩放插值算法,像素风游戏用最近邻插值,兼顾性能和显示效果。
  4. 初始化离屏图像时用显卡兼容的格式创建,开启硬件加速。

核心修改代码

Game.java 修正初始化逻辑

import javax.swing.JFrame;

public class Game {
  public static void main(String[] args) {
      JFrame window = new JFrame("Platformer Test");
      window.setContentPane(new GamePanel(window));
      window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      window.setResizable(false);
      window.setUndecorated(true); // 全屏必须关闭窗口边框
      window.pack();
      window.setVisible(true);  
  }
}

GamePanel.java 修正全屏逻辑和渲染逻辑

首先补充缺少的导入:

import java.awt.DisplayMode;
import java.awt.RenderingHints;
import java.awt.image.BufferStrategy;

修改全屏设置方法:

private void setFullscreen(boolean t) {
    if(t) {
        DisplayMode screenMode = device.getDisplayMode();
        setPreferredSize(new Dimension(screenMode.getWidth(), screenMode.getHeight()));
        device.setFullScreenWindow(frame);
        frame.createBufferStrategy(2); // 创建双缓冲策略
        requestFocus();
    }else {
        setPreferredSize(new Dimension(WIDTH * SCALE, HEIGHT * SCALE));
        device.setFullScreenWindow(null);
        requestFocus();
    }
}

修改init方法里的离屏图像创建逻辑,换成硬件加速兼容格式:

private void init() {
    // 创建硬件加速兼容的离屏图像,替换原来的new BufferedImage
    GraphicsConfiguration gc = device.getDefaultConfiguration();
    image = gc.createCompatibleImage(WIDTH, HEIGHT);
    g = (Graphics2D) image.getGraphics();
    running = true;
    gsm = new GameStateManager();
}

重写render方法:

private void render() {
    gsm.render(g);
    int fps = 0;

    BufferStrategy bs = frame.getBufferStrategy();
    Graphics g2 = bs.getDrawGraphics();
    // 开启最近邻插值,缩放最快,像素风显示无模糊
    ((Graphics2D)g2).setRenderingHint(
        RenderingHints.KEY_INTERPOLATION,
        RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR
    );
    // 自动适配窗口尺寸拉伸绘制
    g2.drawImage(image, 0, 0, frame.getWidth(), frame.getHeight(), null);

    if(renderFPS) {
        fps = frames;
    }
    g2.setColor(Color.red);
    g2.drawString("FPS: " + fps, 100,100);
    g2.dispose();
    bs.show(); // 翻页显示渲染完成的帧
}

补充说明:如果不需要做复古像素风,把插值模式换成VALUE_INTERPOLATION_BILINEAR即可,性能损耗极小。改完后全屏帧率基本可以和窗口模式持平,不会出现20~70帧的暴跌情况。

内容的提问来源于stack exchange,提问作者jang1er

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 17:06:26