用java实现一份流星雨,可以加背景图,并写好注释和原理
时间: 2024-02-24 07:53:10 浏览: 131
好的,下面是Java实现流星雨的代码,包含注释和原理解释。
```java
import java.awt.*;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.Random;
import javax.swing.*;
public class MeteorShower extends JPanel implements Runnable {
private static final long serialVersionUID = 1L;
private static final int WIDTH = 600; // 画布宽度
private static final int HEIGHT = 400; // 画布高度
private static final int MAX_METEORS = 10; // 最大流星数
private static final int MAX_TAIL_LENGTH = 20; // 流星最大长度
private static final int MIN_TAIL_LENGTH = 5; // 流星最小长度
private static final int MAX_SPEED = 8; // 流星最大速度
private static final int MIN_SPEED = 3; // 流星最小速度
private static final int METEOR_CHANCE = 5; // 流星出现几率,值越大出现越少
private static final int BACKGROUND_UPDATE_FREQUENCY = 10; // 背景更新频率,值越大更新越慢
private static final int BACKGROUND_STARS = 200; // 背景星星数量
private BufferedImage backgroundImage; // 背景图
private Graphics2D graphics; // 画布
private ArrayList<Meteor> meteors; // 流星列表
public MeteorShower() {
setPreferredSize(new Dimension(WIDTH, HEIGHT));
setBackground(Color.BLACK);
meteors = new ArrayList<Meteor>();
backgroundImage = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
graphics = (Graphics2D) backgroundImage.getGraphics();
generateBackground();
}
private void generateBackground() {
Random random = new Random();
// 绘制背景星星
for (int i = 0; i < BACKGROUND_STARS; i++) {
int x = random.nextInt(WIDTH);
int y = random.nextInt(HEIGHT);
int brightness = random.nextInt(256);
graphics.setColor(new Color(brightness, brightness, brightness));
graphics.fillRect(x, y, 1, 1);
}
}
private void updateBackground() {
Random random = new Random();
// 随机更新背景星星亮度
for (int i = 0; i < HEIGHT; i++) {
for (int j = 0; j < WIDTH; j++) {
int rgb = backgroundImage.getRGB(j, i);
Color color = new Color(rgb);
if (random.nextInt(BACKGROUND_UPDATE_FREQUENCY) == 0) {
int brightness = color.getRed() + random.nextInt(3) - 1;
if (brightness < 0) {
brightness = 0;
} else if (brightness > 255) {
brightness = 255;
}
backgroundImage.setRGB(j, i, new Color(brightness, brightness, brightness).getRGB());
}
}
}
}
private void drawBackground(Graphics2D g) {
g.drawImage(backgroundImage, 0, 0, null);
}
private void drawMeteors(Graphics2D g) {
for (Meteor meteor : meteors) {
meteor.draw(g);
}
}
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
drawBackground(graphics);
drawMeteors(graphics);
g.drawImage(backgroundImage, 0, 0, null);
}
@Override
public void run() {
Random random = new Random();
while (true) {
// 添加新的流星
if (meteors.size() < MAX_METEORS && random.nextInt(METEOR_CHANCE) == 0) {
int x = random.nextInt(WIDTH);
int y = random.nextInt(HEIGHT / 2);
int tailLength = random.nextInt(MAX_TAIL_LENGTH - MIN_TAIL_LENGTH) + MIN_TAIL_LENGTH;
int speed = random.nextInt(MAX_SPEED - MIN_SPEED) + MIN_SPEED;
meteors.add(new Meteor(x, y, tailLength, speed));
}
// 更新流星位置
for (Meteor meteor : meteors) {
meteor.update();
}
// 更新背景星星
updateBackground();
// 重绘画布
repaint();
// 等待一段时间
try {
Thread.sleep(30);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
private class Meteor {
private int x; // 流星起点横坐标
private int y; // 流星起点纵坐标
private int tailLength; // 流星长度
private int speed; // 流星速度
private int tailX[]; // 流星尾巴横坐标
private int tailY[]; // 流星尾巴纵坐标
public Meteor(int x, int y, int tailLength, int speed) {
this.x = x;
this.y = y;
this.tailLength = tailLength;
this.speed = speed;
tailX = new int[tailLength];
tailY = new int[tailLength];
// 初始化流星尾巴坐标
for (int i = 0; i < tailLength; i++) {
tailX[i] = x;
tailY[i] = y;
}
}
public void update() {
// 更新流星尾巴坐标
for (int i = tailLength - 1; i > 0; i--) {
tailX[i] = tailX[i - 1];
tailY[i] = tailY[i - 1];
}
// 更新流星起点坐标
x -= speed;
if (x < 0) {
x = WIDTH;
y = new Random().nextInt(HEIGHT / 2);
}
tailX[0] = x;
tailY[0] = y;
}
public void draw(Graphics2D g) {
g.setColor(Color.WHITE);
// 绘制流星尾巴
for (int i = 0; i < tailLength - 1; i++) {
int x1 = tailX[i];
int y1 = tailY[i];
int x2 = tailX[i + 1];
int y2 = tailY[i + 1];
g.drawLine(x1, y1, x2, y2);
}
// 绘制流星头
int x1 = tailX[tailLength - 1];
int y1 = tailY[tailLength - 1];
int x2 = x;
int y2 = y;
g.drawLine(x1, y1, x2, y2);
}
}
public static void main(String[] args) {
JFrame frame = new JFrame("Meteor Shower");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
MeteorShower meteorShower = new MeteorShower();
frame.add(meteorShower);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
new Thread(meteorShower).start();
}
}
```
原理解释:
1. 通过继承 JPanel 类实现画布。
2. 在画布上绘制流星和背景星星。
3. 使用线程不断更新流星和背景星星的位置,并重绘画布。
4. 流星的尾巴长度、速度、出现几率等参数都通过常量定义。
5. 背景星星的数量和亮度更新频率也通过常量定义。
阅读全文