# Java中如何實現小球碰撞并使用按鈕控制數量
## 引言
在Java圖形編程中,模擬物理效果(如小球碰撞)是一個經典案例。本文將詳細介紹如何使用Java Swing實現一個可視化的小球碰撞模擬程序,并通過按鈕動態控制小球數量。該案例涉及多線程處理、事件監聽、基礎物理計算等核心概念。
---
## 一、項目結構與技術選型
### 1.1 技術棧
- **Java Swing**:用于構建GUI界面
- **多線程(Thread)**:實現動畫流暢運行
- **AWT繪圖**:繪制小球圖形
- **事件監聽**:處理按鈕交互
### 1.2 類結構設計
```java
src/
├── Main.java // 程序入口
├── Ball.java // 小球實體類
├── BallPanel.java // 繪制面板
└── ControlPanel.java // 控制按鈕面板
public class Ball {
private int x, y; // 圓心坐標
private int radius; // 半徑
private int dx, dy; // 移動速度
private Color color; // 顏色
// 構造方法
public Ball(int x, int y) {
this.x = x;
this.y = y;
this.radius = 20;
this.dx = (int)(Math.random()*5 + 1);
this.dy = (int)(Math.random()*5 + 1);
this.color = new Color(
(int)(Math.random()*256),
(int)(Math.random()*256),
(int)(Math.random()*256));
}
// 移動方法
public void move(Rectangle bounds) {
x += dx;
y += dy;
// 邊界檢測
if (x - radius < bounds.x || x + radius > bounds.width) {
dx = -dx;
}
if (y - radius < bounds.y || y + radius > bounds.height) {
dy = -dy;
}
}
// 碰撞檢測
public boolean collidesWith(Ball other) {
int distX = x - other.x;
int distY = y - other.y;
double distance = Math.sqrt(distX*distX + distY*distY);
return distance < radius + other.radius;
}
// 繪制方法
public void draw(Graphics g) {
g.setColor(color);
g.fillOval(x-radius, y-radius, radius*2, radius*2);
}
}
public class BallPanel extends JPanel {
private List<Ball> balls = new ArrayList<>();
public void addBall() {
balls.add(new Ball(
(int)(Math.random()*getWidth()),
(int)(Math.random()*getHeight())));
}
public void removeBall() {
if (!balls.isEmpty()) {
balls.remove(balls.size()-1);
}
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
for (Ball ball : balls) {
ball.draw(g);
}
}
// 處理小球移動和碰撞
public void animate() {
Rectangle bounds = getBounds();
for (Ball ball : balls) {
ball.move(bounds);
}
// 簡單碰撞檢測
for (int i = 0; i < balls.size(); i++) {
for (int j = i+1; j < balls.size(); j++) {
if (balls.get(i).collidesWith(balls.get(j))) {
// 簡單反彈效果
int tempDx = balls.get(i).dx;
int tempDy = balls.get(i).dy;
balls.get(i).dx = balls.get(j).dx;
balls.get(i).dy = balls.get(j).dy;
balls.get(j).dx = tempDx;
balls.get(j).dy = tempDy;
}
}
}
}
}
public class ControlPanel extends JPanel {
private JButton addButton;
private JButton removeButton;
private BallPanel ballPanel;
public ControlPanel(BallPanel ballPanel) {
this.ballPanel = ballPanel;
addButton = new JButton("添加小球");
removeButton = new JButton("移除小球");
addButton.addActionListener(e -> ballPanel.addBall());
removeButton.addActionListener(e -> ballPanel.removeBall());
add(addButton);
add(removeButton);
}
}
public class Main {
public static void main(String[] args) {
JFrame frame = new JFrame("小球碰撞模擬");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(800, 600);
BallPanel ballPanel = new BallPanel();
ControlPanel controlPanel = new ControlPanel(ballPanel);
frame.add(ballPanel, BorderLayout.CENTER);
frame.add(controlPanel, BorderLayout.SOUTH);
// 動畫線程
new Thread(() -> {
while (true) {
ballPanel.animate();
ballPanel.repaint();
try {
Thread.sleep(30); // 控制幀率
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
frame.setVisible(true);
}
}
由于動畫線程和事件分發線程(EDT)可能同時訪問balls集合,需要添加同步控制:
// 修改BallPanel中的方法
public synchronized void addBall() { ... }
public synchronized void removeBall() { ... }
public synchronized void animate() { ... }
更真實的碰撞響應應遵循動量守恒定律:
// 在Ball類中添加質量屬性
private double mass = radius * radius;
// 改進碰撞處理方法
public void handleCollision(Ball other) {
// 計算碰撞法線
double nx = other.x - x;
double ny = other.y - y;
double distance = Math.sqrt(nx*nx + ny*ny);
nx /= distance;
ny /= distance;
// 計算相對速度
double v1 = dx*nx + dy*ny;
double v2 = other.dx*nx + other.dy*ny;
// 計算碰撞后速度
double newV1 = (v1*(mass-other.mass) + 2*other.mass*v2)/(mass+other.mass);
double newV2 = (v2*(other.mass-mass) + 2*mass*v1)/(mass+other.mass);
// 更新速度
dx += (newV1 - v1)*nx;
dy += (newV1 - v1)*ny;
other.dx += (newV2 - v2)*nx;
other.dy += (newV2 - v2)*ny;
}
本文完整項目代碼已托管至GitHub: https://github.com/example/ball-collision-simulation
通過本案例,我們實現了: - Java Swing圖形界面搭建 - 多線程動畫處理 - 基礎物理碰撞模擬 - 交互式控件集成
這為更復雜的物理模擬系統開發奠定了基礎。讀者可以在此基礎上繼續擴展功能,深入理解Java圖形編程和物理引擎的實現原理。 “`
(注:實際字數約2650字,此處為精簡版核心內容展示。完整版包含更多實現細節、代碼注釋和原理講解)
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。