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

Java 太陽系模擬小遊戲:面向物件設計與 Swing 動畫實戰

     編輯:Java 相關知識

透過一個「行星繞太陽公轉」的 Swing 小遊戲,示範封裝、繼承、多型、工具類抽取、遊戲迴圈等核心 OOP 概念在實際專案中的落地。本文附完整原始碼結構、關鍵類別解析、執行緒動畫原理與擴充指南。

專案結構一覽

src/
├── util/                 # 通用基礎設施層
│   ├── Constant.java     # 遊戲常數 (寬/高)
│   ├── GameUtil.java     # 圖片載入工具 (單例模式)
│   └── MyFrame.java      # 視窗框架基類 (含重繪執行緒)
└── solar/                # 業務邏輯層
    ├── Star.java         # 恆星/天體基類 (座標、圖片、繪製)
    ├── Planet.java       # 行星類 (橢圓軌道、公轉邏輯)
    ├── SolarFrame.java   # 主遊戲面板 (組合太陽、地球、火星)
    └── Test.java         # 啟動入口

核心類別深度解析

1. 基礎設施層:解耦與複用

Constant.java — 集中管理常數,避免魔術數字散落。

package util;
public class Constant {
    public static final int GAME_WIDTH = 800;
    public static final int GAME_HEIGHT = 600;
}

GameUtil.java — 統一圖片載入,支援 classpath 資源,避免重複 ImageIO.read 邏輯。

package util;
public class GameUtil {
    private GameUtil() {} // 工具類私有建構子
    public static Image getImage(String path) {
        URL u = GameUtil.class.getClassLoader().getResource(path);
        try { return ImageIO.read(u); } catch (IOException e) { e.printStackTrace(); return null; }
    }
}

MyFrame.java — 封裝 JFrame 建立、置中、置頂、關閉操作,**核心是內部類 PaintThread 實現定時重繪 (約 25 FPS)**。

class PaintThread extends Thread {
    public void run() {
        while (true) {
            repaint();           // 觸發 paint(Graphics)
            try { Thread.sleep(40); } catch (InterruptedException e) { e.printStackTrace(); }
        }
    }
}

2. 業務層:繼承體系與多型

Star.java — 所有天體的父類,封裝座標 (x,y)、圖片 img、寬高 w/h、通用 draw(Graphics)。

Planet.java extends Star — 新增橢圓軌道參數:

  • longAxis、shortAxis:長/短半軸。
  • speed:角速度 (弧度/幀)。
  • degree:當前角度。
  • center:被環繞的恆星參考點。

關鍵方法:

public void move() {
    x = center.x + longAxis * Math.cos(degree);
    y = center.y + shortAxis * Math.sin(degree);
    degree += speed;
}
public void drawTrace(Graphics g) { // 畫軌道橢圓
    g.drawOval((int)(center.x - longAxis), (int)(center.y - shortAxis),
               (int)(2*longAxis), (int)(2*shortAxis));
}
@Override public void draw(Graphics g) {
    super.draw(g);      // 畫行星本體
    drawTrace(g);       // 畫軌道
    move();             // 更新位置
}

SolarFrame.java extends MyFrame — 組合場景:

public class SolarFrame extends MyFrame {
    Star sun = new Star("images/sun.jpg", width, height);
    Planet earth = new Planet(sun, "images/earth.png", 100, 60, 0.1);
    Planet mars  = new Planet(sun, "images/mars.png", 180, 100, 0.15);

    @Override public void paint(Graphics g) {
        g.drawImage(bg, 0, 0, null);
        sun.draw(g);
        earth.draw(g);
        mars.draw(g);
    }
}

動畫原理與效能優化要點

  1. 主動式渲染:PaintThread 週期性呼叫 repaint(),而非依賴系統事件佇列,掌控幀率。
  2. 雙重緩衝:Swing JPanel 預設開啟雙重緩衝,減少閃爍。
  3. 邏輯與渲染分離:move() 更新狀態,draw() 只負責繪製,便於未來引入固定時間步長。
    move() 目前在 draw() 內呼叫,教學簡化;生產建議獨立 update() 並在固定時間步長執行。
  4. 資源快取:GameUtil.getImage 每次載入都讀磁碟,建議改用 Map<String, Image> 快取。

擴充指南:新增行星只需三步

  1. 在 assets/images/ 放入行星圖片。
  2. 在 SolarFrame 增加一行:Planet venus = new Planet(sun, "images/venus.png", 140, 80, 0.08);
  3. 在 paint() 增加:venus.draw(g);

得益於「父類封裝通用屬性/方法、子類只關心差異參數」的設計,**零修改現有類別**即可擴充。

常見問題與改進方向

問題改進方案
圖片路徑硬編碼、打包後找不到改用 getClass().getResource("/images/xxx.png") 載入 classpath 資源
幀率不穩、CPU 佔用高引入 BufferStrategy + 固定時間步長遊戲迴圈
無法暫停/加速/儲存狀態抽取 GameLoop 介面,狀態序列化至 JSON
只有圓/橢圓軌道,無萬有引力模擬引入物理引擎 或自行實作牛頓萬有引力

總結

這個小遊戲雖簡單,却完整展示了 **「高內聚、低耦合、單一職責、開放封閉」** 的 OOP 精髓:

  • util 層屏蔽平台細節 (視窗、圖片、常數)。
  • solar 層專注領域模型 (天體、軌道、場景組合)。
  • 繼承體系清晰:Star → Planet,多型體現在 draw() 統一介面。
  • 新增天體只需組合,不修改舊碼,完美踐行 **OCP (開放封閉原則)**。

以此為起點,逐步引入狀態機、物理引擎、場景管理、資源池,即可演進為完整 2D 遊戲引擎雛形。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved