首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java Applet 彈球動畫:從閃爍問題到雙緩衝完美解決

     編輯:Java 相關知識

問題背景

早期 Java Applet 繪製動畫時,直接在 paint() 繪圖會產生嚴重閃爍,因為預設 update() 會先清除畫面再呼叫 paint()。

版本一:單緩衝(有閃爍)

public class OnlyChangeUpdate extends Applet implements Runnable {
    int x, y, dx=20, dy=20, w, h;
    Thread t;
    public void init() {
        w = getSize().width; h = getSize().height;
        setBackground(Color.black);
    }
    public void start() { t = new Thread(this); t.start(); }
    public void stop()  { t = null; }
    public void paint(Graphics g) {
        g.setColor(Color.white);
        g.fillOval(x, y, 15, 15);
    }
    public void update(Graphics g) { paint(g); } // 取消預設清屏
    public void run() {
        while (t != null) {
            repaint();
            try { Thread.sleep(80); } catch (InterruptedException ignored) {}
            x += dx; y += dy;
            if (x >= w-15) { x = w-15; dx = -dx; }
            if (x <= 0)    { x = 0;    dx = -dx; }
            if (y >= h-15) { y = h-15; dy = -dy+5; }
            if (y <= 0)    { y = 0;    dy = -dy+5; }
        }
    }
}

缺點:update() 仍會閃爍,碰撞邏輯含 +5 魔術數字,物理感不真實。

版本二:雙緩衝(無閃爍)

public class UseDoubleBuffering extends Applet implements Runnable {
    int x, y, dx=2, dy=3, w, h;
    Thread t;
    Image offScreen;
    Graphics offG;
    public void init() {
        w = getSize().width; h = getSize().height;
        offScreen = createImage(w, h);
        offG = offScreen.getGraphics();
    }
    public void start() { t = new Thread(this); t.start(); }
    public void stop()  { t = null; }
    public void paint(Graphics g) {
        offG.setColor(Color.black);
        offG.fillRect(0, 0, w, h);          // 離屏清屏
        offG.setColor(Color.white);
        offG.fillOval(x, y, 15, 15);        // 離屏繪圖
        g.drawImage(offScreen, 0, 0, this); // 一次性貼上螢幕
    }
    public void update(Graphics g) { paint(g); }
    public void run() {
        while (t != null) {
            repaint();
            try { Thread.sleep(50); } catch (InterruptedException ignored) {}
            x += dx; y += dy;
            if (x >= w-15) { x = w-15; dx = -dx; }
            if (x <= 0)    { x = 0;    dx = -dx; }
            if (y >= h-15) { y = h-15; dy = -dy; }
            if (y <= 0)    { y = 0;    dy = -dy; }
        }
    }
}

核心原理解析

  1. 離屏圖像:createImage(w, h) 在記憶體建立一張畫布。
  2. 離屏繪圖:所有繪圖操作導向 offG,螢幕不見中間過程。
  3. 一次性呈現:g.drawImage(offScreen, 0, 0, this) 將完幀一次複製到顯示器,消除閃爍。

現代替代方案

Applet 已被瀏覽器淘汰。新專案請使用:

  • Swing:JPanel 覆寫 paintComponent(),預設即雙緩衝(setDoubleBuffered(true))。
  • JavaFX:場景圖自動處理合成與 VSync,效能更優。
  • HTML5 Canvas / WebGL:瀏覽器原生、跨平台、無需外掛。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved