小球在矩形邊界內運動,位置 (x, y)、速度分量 (vx, vy)。每幀更新位置,檢測邊界碰撞並反轉對應速度分量:
// 位置更新
if (addX) x += 3; else x -= 3;
if (addY) y += 6; else y -= 6;
// 邊界碰撞檢測(假設小球直徑 50,面板寬高 width/height)
if (x <= 0 || x >= (width - 50)) addX = !addX; // 水平反彈
if (y <= 0 || y >= (height - 50)) addY = !addY; // 垂直反彈
addX/addY 為布爾標誌位,代表當前運動方向。速度大小固定(3, 6),方向由標誌位決定。碰撞時取反標誌位即實現速度反向。
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class BouncingBall extends JPanel implements ActionListener {
private int x = 50, y = 50; // 初始位置
private int vx = 3, vy = 6; // 速度向量
private final int BALL_SIZE = 50; // 球直徑
private Timer timer;
public BouncingBall() {
timer = new Timer(16, this); // ~60 FPS
timer.start();
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.RED);
g.fillOval(x, y, BALL_SIZE, BALL_SIZE);
}
@Override
public void actionPerformed(ActionEvent e) {
int width = getWidth();
int height = getHeight();
x += vx;
y += vy;
// 邊界碰撞:位置修正 + 速度反向
if (x <= 0) { x = 0; vx = -vx; }
else if (x >= width - BALL_SIZE) { x = width - BALL_SIZE; vx = -vx; }
if (y <= 0) { y = 0; vy = -vy; }
else if (y >= height - BALL_SIZE) { y = height - BALL_SIZE; vy = -vy; }
repaint(); // 觸發重繪
}
public static void main(String[] args) {
JFrame frame = new JFrame("Bouncing Ball Demo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new BouncingBall());
frame.setSize(600, 400);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
| 要素 | 說明 |
|---|---|
| 座標系原點 | 左上角 (0,0),x 向右,y 向下 |
| 碰撞檢測時機 | 位置更新 後 檢測,並將位置夾緊在邊界內(避免卡在牆外) |
| 速度反向 | vx = -vx 比布爾標誌位更直觀,支援變速、摩擦力擴展 |
| 繪製線程 | Swing Timer 在 EDT 執行,安全更新 UI 狀態並觸發重繪 |
| 幀率控制 | 16ms ≈ 60 FPS;複雜場景建議使用 System.nanoTime() 計算增量時間 |
<= r1+r2,彈性碰撞動量守恆公式交換速度分量。vy += gravity;碰撞底部時 vy *= -restitution; vx *= friction。distance(center) + radius >= R;多邊形用射線法或 SAT 分離軸定理。BufferStrategy 或 JavaFX AnimationTimer 替代 Swing 獲取更高性能。邊界反彈是遊戲物理與動畫編程的入門基石。核心在於「位置積分更新 → 邊界檢測 → 速度反向/修正 → 觸發重繪」的循環。理解此模式,即可擴展至複雜的剛體模擬、粒子系統與遊戲引擎開發。