欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

多线程实现烟花效果

程序员文章站 2024-03-18 10:38:40
...

文章的代码借鉴于一篇CSDN文章《传说中的烟花程序》,里面的烟花效果十分好看,给了我很大的帮助。做了一个简单的烟花效果图。
多线程实现烟花效果
通过鼠标点击,绽放烟花,仍有许多不足的地方
这里是通过一个线程使烟花绽放,而不是将烟花的每一个点建立一个线程,操作起来更为简单

下面有一张影视剧图作为背景,用萤火虫来代替原先的烟花点,十分好看,为编程带来很多乐趣
多线程实现烟花效果
这张图片营造了一个很好的意境,但是在烟花方面也有一些不足

在烟花的编程中会遇到的问题

  1. 如何展现烟花的效果
    这里需要的便是公式,然随机产生的小球分布成圆的形状

代码如下

 		
    //确定线的角度
	double angleXy = random.nextDouble() * 2 * Math.PI;
	//确定线上的点
	double angleZ = random.nextDouble() * 2 * Math.PI;
	double velocity = brithvelocity* Math.cos(angleZ);
  1. 如何让烟花的颜色更加的好看
    颜色可以通过一些公式让随机的颜色统一,并且增加颜色的亮度,所以我们每一个烟花里烟花点的颜色一样,不同的烟花颜色存在差异

    代码如下

       //颜色进行随机设置
		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);
  1. 烟花消失的背景色问题
    如果要让烟花消失,背景色必须选择为黑色,因为在后续的过程中因为与背景色融为一体,所以我们只会看到呈现为圆形的烟花,如果不喜欢背景色,可以选择图片代替烟花点

  2. 呈现圆形烟花之后问题
    可根据不同的数学物理方式,来对其进行操作

共有四个类

  1. 窗体类
  2. 监听器类
  3. 小球类
  4. 音乐类

窗体类

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

希望这篇文章对大家烟花的编写有所帮助