Java在小游戏中使用双缓冲遇到的问题

最近在尝试用Java做出一些经典小游戏,在被画面闪烁折磨之后,上网搜索学会了(大概)双缓冲,成功消除了画面闪烁。
接着发现了两个问题:
1.在之后的另一个代码中,我图省事(),没有专门做一个继承Canvas的类,而是把主类继承JFrame,直接重写了JFrame中的paint(Graphics g)方法和update(Graphics g),在程序中直接调用repaint()方法。但是发现闪烁又出现了。
我在VS Code里面按住Ctrl点击repaint()查看repaint()的代码,发现这个里面似乎没有调用update和paint

public void repaint() {
        repaint(0, 0, 0, width, height);
}
public void repaint(long tm, int x, int y, int width, int height) {
        if (this.peer instanceof LightweightPeer) {
            // Needs to be translated to parent coordinates since
            // a parent native container provides the actual repaint
            // services.  Additionally, the request is restricted to
            // the bounds of the component.
            if (parent != null) {
                if (x < 0) {
                    width += x;
                    x = 0;
                }
                if (y < 0) {
                    height += y;
                    y = 0;
                }

                int pwidth = (width > this.width) ? this.width : width;
                int pheight = (height > this.height) ? this.height : height;

                if (pwidth <= 0 || pheight <= 0) {
                    return;
                }

                int px = this.x + x;
                int py = this.y + y;
                parent.repaint(tm, px, py, pwidth, pheight);
            }
        } else {
            if (isVisible() && (this.peer != null) &&
                (width > 0) && (height > 0)) {
                PaintEvent e = new PaintEvent(this, PaintEvent.UPDATE,
                                              new Rectangle(x, y, width, height));
                SunToolkit.postEvent(SunToolkit.targetToAppContext(this), e);
            }
        }
    }

后面把代码里面的repaint()全部替换成了update(getGraphics())解决了这个问题,但还是有点不清楚(还有Canvas的repaint()好像只有定义)
2.在替换之后,虽然闪烁没了,但是感觉画面清晰度降低了很多。

img


(还没上图片不要介意)
这是替换前的

img


这是替换后的

我猜可能是因为系统缩放的问题,但是不清楚怎么解决……
(方法倒也有,把缓冲用的图片分辨率加大,然后对应的把paint()里面的所有东西都放大,最后按照正常大小显示在屏幕上。但是似乎很费手)


// --------------用于绘图的部分
    @Override // 重写paint
    public void paint(Graphics g) {
        super.paint(g);
        Graphics2D g2 = (Graphics2D) g;

        // 绘制玩家
        g2.rotate(-Math.atan(1.0 * vy / VX), p.x + p.width / 2, p.y + p.height / 2);
        g2.fill(p);
        g2.drawLine(p.x + p.width / 2, p.y + p.height / 2, p.x + p.width / 2 + 30, p.y + p.height / 2);
        g2.rotate(Math.atan(1.0 * vy / VX), p.x + p.width / 2, p.y + p.height / 2);

        if (game == Game.START) {
            g2.drawString("按下鼠标开始", W / 2, H / 2);
        } else if (game == Game.RUNNING || game == Game.ZT) {
            g2.setColor(Color.GREEN);
            g2.fillRect((int) (objx1), 0, (int) (objW), (int) objy1);
            g2.fillRect((int) objx1, (int) (objy1 + objH), (int) (objW), (int) (H - objH - objy1));
            g2.fillRect((int) objx2, 0, (int) objW, (int) objy2);
            g2.fillRect((int) objx2, (int) (objy2 + objH), objW, (int) (H - objH - objy2));
        } else if (game == Game.AGAIN) {
            g2.setColor(Color.GREEN);
            g2.fillRect((int) (objx1), 0, (int) (objW), (int) objy1);
            g2.fillRect((int) objx1, (int) (objy1 + objH), (int) (objW), (int) (H - objH - objy1));
            g2.fillRect((int) objx2, 0, (int) objW, (int) objy2);
            g2.fillRect((int) objx2, (int) (objy2 + objH), objW, (int) (H - objH - objy2));
            g2.setColor(Color.RED);
            g2.drawString("游戏结束!", W / 2, H / 2);
            g2.drawString("你获得了 " + s + " 分!", W / 2 - 10, H / 2 + 15);
            if (s > maxs) {
                g2.setColor(Color.YELLOW);
                g2.drawString("并且获得了最高分!", W / 2 - 20, H / 2 + 30);
            }
        }

        // 暂停键
        g2.setColor(Color.black);
        g2.fillRect(0, 20, 10, 30);
        g2.fillRect(20, 20, 10, 30);

        // 计分
        if (s <= maxs) {
            g2.setColor(Color.black);
        } else {
            g2.setColor(Color.BLACK);
            g2.fillRect(W-30, 30, 30, 10);
            g2.setColor(Color.yellow);
        }
        g2.drawString(String.format("%03d", s), W - 30, 40);
    }

    // 缓存刷新防闪烁
    @Override
    public void update(Graphics g) {
        r = null;
        r = this.createImage(W, H);
        Graphics og = r.getGraphics();
        paint(og);
        g.drawImage(r, 0, 0, this);
    }

img

在资源管理器中可执行文件上点鼠标右键、属性、兼容性、更改高DPI设置、……