渲染具有更改分辨率可能性的 2D 游戏的最有效方法是什么?

What is the most efficient way of rendering 2D game with the possibility of changing the resolution?

我试过:

1.Creating 一个名为 "factor" 的单独变量,并用它乘以或除以字面上的所有内容:实体速度、对象大小、字体、分辨率等。 (该系数始终与分辨率有关,因此对象可以正确缩放)

public class Player extends Entity{

    float size;

    public Player(needed variables) {
        super(needed variables);
        resize();
    }

    public void resize() {
        /*
        Resize everything.
        This method is supposed to be called from a separate resizing
        function located in another class when the JFrame size is changed.

        the function has to play with the choice between divide or multiply
        variables with the factor
        */
    }

    public void tick() {
        x += velX*factor;
        y += velY*factor;
    }

    etc..

}

通过使用这个因子来乘以所有内容,有时会使代码变得非常混乱且难以阅读。

2.Rendering 到 BufferedImage 并缩放 BufferedImage 以适应 JFrame。

void render() {
    //Render the game to a new BufferedImage
    BufferedImage renderedFrame = new BufferedImage(1920, 1080, BufferedImage.TYPE_RGB);
    renderedFrame.createGraphics();
    Graphics g = renderedFrame.getGraphics();

    //Render the game ....

    //Scale the BufferedImage to fit the current resolution and render it to the Canvas
    BufferStrategy bs = getBufferStrategy();
    Graphics f = bs.getDrawGraphics();
    f.drawImage(renderedFrame.getScaledInstance(1280, 720, Image.SCALE_FAST), 0, 0, null);

    f.dispose();
    bs.show();
}

这使代码更具可读性,但随之而来的是 2 个问题:

鼠标输入问题和调整 BufferedImage 的大小占用了太多资源,导致游戏延迟。

3.I 基本上可以尝试为游戏制作一个单独的单位系统.. 但同样的问题是,当涉及到渲染字符串或矩形时,我必须将所有内容乘以因子和之后的代码很糟糕。

有没有更好的2D游戏渲染方式?如果没有,那么我会考虑转向 OpenGL。

提前致谢。

我最成功的方法是缩放图形对象。您最终会得到如下内容:

final int gameUnitsPerScreenDim = 32;

void render(JPanel panel, Graphics2D g2) {
    double pixelHeight = panel.getHeight();
    double pixelsPerGameUnit = pixelHeight / gameUnitsPerScreenDim;

    g2.scale(pixelsPerGameUnit, pixelsPerGameUnit);

    ...
}

然后对于模拟,您使用游戏单元。游戏单元实际有多大有点随意,但如果您正在制作平铺游戏,则可能有一些明显的价值。

而不是使用 scale, you can also create an AffineTransform 可以重复使用它:

if (this.tf == null || /* image size changed since the last frame */) {
    ...
    this.tf = AffineTransform.getScaleInstance(pxPerGu, pxPerGu);
}
g2.setTransform(this.tf);

(每次调用 scale 都会创建一个新的 AffineTransform。)

这甚至更有效了一点,虽然可能不会太高。

(如果你愿意,你也可以使用变换来反转 y 轴并平移,使原点位于图像的中心。这使得很多三角函数和东西感觉更自然。反转 y -axis 使处理文本变得很痛苦。)

此外,使用 OpenGL 可能更好。为了好玩而使用 Swing 编写了几个简单的游戏,我看不出这样做的充分理由。