多线程实现烟花效果
程序员文章站
2024-03-18 10:38:40
...
文章的代码借鉴于一篇CSDN文章《传说中的烟花程序》,里面的烟花效果十分好看,给了我很大的帮助。做了一个简单的烟花效果图。
通过鼠标点击,绽放烟花,仍有许多不足的地方
这里是通过一个线程使烟花绽放,而不是将烟花的每一个点建立一个线程,操作起来更为简单
下面有一张影视剧图作为背景,用萤火虫来代替原先的烟花点,十分好看,为编程带来很多乐趣
这张图片营造了一个很好的意境,但是在烟花方面也有一些不足
在烟花的编程中会遇到的问题
- 如何展现烟花的效果
这里需要的便是公式,然随机产生的小球分布成圆的形状
代码如下
//确定线的角度
double angleXy = random.nextDouble() * 2 * Math.PI;
//确定线上的点
double angleZ = random.nextDouble() * 2 * Math.PI;
double velocity = brithvelocity* Math.cos(angleZ);
-
如何让烟花的颜色更加的好看
颜色可以通过一些公式让随机的颜色统一,并且增加颜色的亮度,所以我们每一个烟花里烟花点的颜色一样,不同的烟花颜色存在差异代码如下
//颜色进行随机设置
int r = random.nextInt(256);
int gc = random.nextInt(256);
int b = random.nextInt(256);
// 这一步为选取r,g,b中的最大值,进行一系列变换使r,g,b得到的color最亮
int max = r > gc ? r : gc;
max = max > b ? max : b;
double brighter = 255.0 / max;
r = (int) (r * brighter);
gc = (int) (gc * brighter);
b = (int) (b * brighter);
color = new Color(r, gc, b);
-
烟花消失的背景色问题
如果要让烟花消失,背景色必须选择为黑色,因为在后续的过程中因为与背景色融为一体,所以我们只会看到呈现为圆形的烟花,如果不喜欢背景色,可以选择图片代替烟花点 -
呈现圆形烟花之后问题
可根据不同的数学物理方式,来对其进行操作
共有四个类
- 窗体类
- 监听器类
- 小球类
- 音乐类
窗体类
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.Random;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
//添加线程
public class GameUI extends JFrame implements Runnable {
// ball list
ArrayList<Ball> ballList = new ArrayList<>();
// 画笔
Graphics g;
// 获取缓冲图片
BufferedImage buffimage = new BufferedImage(1000, 1000, BufferedImage.TYPE_INT_ARGB);
// 从缓冲图片上获取画笔
Graphics buffg = buffimage.getGraphics();
/**
* 初始化界面 启动线程 向对列中添加小球
*/
public void initUI() {
setTitle("烟花");
setSize(1000, 1000);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
setVisible(true);
g = this.getGraphics();
// 添加监听器 鼠标 鼠标移动拖动
BallListener bl = new BallListener(g, ballList);
this.addMouseMotionListener(bl);
this.addMouseListener(bl);
// 启动绘制线程
Thread t1 = new Thread(this);
t1.start();
}
@Override
public void run() {
while (true) {
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
// 缓冲画笔 绘制背景图片
//一般背景
Image image = new ImageIcon("bj.png").getImage();
//东宫背景
// Image image = new ImageIcon("donggong1.jpg").getImage();
buffg.drawImage(image, 0, 0, null);
// 缓冲画笔 绘制小球 移动小球
for (int i = 0; i < ballList.size(); i++) {
Ball ball = ballList.get(i);
ball.drawBall(buffg);
// ball.moveBall();
}
// 画笔绘制缓冲图片
g.drawImage(buffimage, 0, 0, null);
}
}
// 主方法
public static void main(String[] args) {
GameUI game = new GameUI();
game.initUI();
new Music("C:\\Users\\89655\\Desktop\\小时-爱殇-(电视剧《东宫》插曲).mp3").start();
}
}
监听器类
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.Random;
// 小球监听
public class BallListener extends MouseAdapter {
Graphics g;
double brithvelocity = 80;
int count = 400;
ArrayList<Ball> ballList;
// 随机数
Random random = new Random();
Color color;
// 监听器构造方法
public BallListener(Graphics g, ArrayList<Ball> ballList) {
this.g = g;
this.ballList = ballList;
}
public void mouseClicked(MouseEvent e){
//颜色进行随机设置
int r = random.nextInt(256);
int gc = random.nextInt(256);
int b = random.nextInt(256);
// 这一步为选取r,g,b中的最大值,进行一系列变换使r,g,b得到的color最亮
int max = r > gc ? r : gc;
max = max > b ? max : b;
double brighter = 255.0 / max;
r = (int) (r * brighter);
gc = (int) (gc * brighter);
b = (int) (b * brighter);
color = new Color(r, gc, b);
for(int i = 0; i < count; i++) {
// 准备小球数据
double x = e.getX();
double y = e.getY();
double size = random.nextInt(5) + 1;
//确定线的角度
double angleXy = random.nextDouble() * 2 * Math.PI;
//确定线上的点
double angleZ = random.nextDouble() * 2 * Math.PI;
double velocity = brithvelocity* Math.cos(angleZ);
Ball ball = new Ball(x, y, size, color,velocity,angleXy);
ballList.add(ball);
}
}
// 鼠标移动
public void mouseMoved(MouseEvent e) {
}
}
小球类
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.image.BufferedImage;
import javax.swing.ImageIcon;
public class Ball {
double x, y, size, speedx, speedy;
double velocity,angleXy;
double stateX, stateY;
double velocityX, velocityY;
double damp = 0.75,gravity = 1.0;
double traceDarkerFactor = 0.70;
Color color;
boolean stateDead;
// 小球构造方法之一
public Ball(double x, double y, double size, Color color,double velocity,double angleXy) {
this.x = x;
this.y = y;
this.size = size;
this.color = color;
this.velocity = velocity;
this.angleXy = angleXy;
stateX = x;
stateY = y;
// 烟花使用
velocityX = velocity * Math.cos(angleXy);
velocityY = velocity * Math.sin(angleXy);
}
// 绘制小球
public void drawBall(Graphics bg) {
//烟花使用
velocityX *= damp;
velocityY += gravity;
velocityY *= damp;
stateX += velocityX;
stateY += velocityY;
bg.setColor(color);
bg.fillRect((int)stateX, (int)stateY, 1, 2);
color = new Color((int) (color.getRed() * traceDarkerFactor),
(int) (color.getGreen() * traceDarkerFactor),
(int) (color.getBlue() * traceDarkerFactor));
if (color.getRed() + color.getGreen() + color.getBlue() < 10)
stateDead = true;
//东宫使用
// velocityX = velocity * Math.cos(angleXy);
// velocityY = velocity * Math.sin(angleXy);
//
// stateX += velocityX;
// stateY += velocityY;
// // 缓冲画笔 绘制背景图片
// Image image = new ImageIcon("guang1.png").getImage();
// bg.drawImage(image, (int)stateX, (int)stateY, null);
}
}
音乐类
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import javazoom.jl.decoder.JavaLayerException;
import javazoom.jl.player.*;
public class Music extends Thread {
Player player;
String music;
Boolean MusicFlag;
public Music(String file) {
this.music = file;
}
public void run() {
try {
play();
}
catch (FileNotFoundException | JavaLayerException e)
{
e.printStackTrace();
}
}
public void play() throws FileNotFoundException, JavaLayerException {
BufferedInputStream buffer = new BufferedInputStream(new FileInputStream(music)); player = new Player(buffer); player.play(); }
}
音乐类需要插入一个包,包的下载地址在下方的链接里
链接:https://pan.baidu.com/s/1GG5Lefd0VxcSgmSGCpaILQ
提取码:xp4o
希望这篇文章对大家烟花的编写有所帮助