java学习之粒子系统(一)——绽放的烟花

一、运用知识

      1、欧拉公式:

           r(t+dt)=r(t)+v(t)*dt;             

           v(t+dt)=v(t)+a(t)*dt;

      2、多线程控制;

      3、双缓冲绘图;

      4、音频文件加入

二、功能实现:

      1、单个烟花定点发射;

      2、烟花爆炸位置、颜色、生命周期等随机;

      3、加入了音效;

      4、使用了双缓冲绘图

      5、引入了背景图;

     6、烟花燃放完自动退出界面

三、效果图

四、代码

     常数类:

package com.Liao.Fireworks0728v0;

public interface Config {
	public static final int SCREEN_WIDTH = 1366;//屏幕宽度
	public static final int SCREEN_HEIGHT = 768;//屏幕高度
	public static final int SIZE = 16;//粒子大小
	public static final double DT  = 0.01;//时间变量
	public static final Vector_2 PSTART=new Vector_2(683,768);//粒子初始位置
	public static final Vector_2 VSTART=new Vector_2(0,-500);//粒子初始速度
	public static final Vector_2 ASTART=new Vector_2(0,200);//粒子初始加速度
}

二维向量类:

package com.Liao.Fireworks0728v0;

public class Vector_2 {
	
	public double x,y;
	
	public Vector_2(double x, double y) {
		super();
		this.x = x;
		this.y = y;
	}
	//向量加法
	public Vector_2  add(Vector_2 v){
		return new Vector_2(this.x+v.x,this.y+v.y);
	}
	//向量乘法
	public Vector_2  multiply(double d){
		return new Vector_2(this.x*d,this.y*d);
	}
}

粒子类

package com.Liao.Fireworks0728v0;

import java.awt.Color;

public class Particle {
	//粒子位置、速度、加速度
	public Vector_2 position, velocity, acceleration;
	//粒子颜色
	public Color color;
	//粒子生命、年龄、宽度、长度
	public int life,age,width,height;

	public Particle() {
	}

	public int getX() {
		return (int) this.position.x;
	}

	public int getY() {
		return (int) this.position.y;
	}
}

主界面

package com.Liao.Fireworks0728v0;

import java.awt.Graphics;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.ImageIcon;
import javax.swing.JFrame;

public class MainUI extends JFrame implements Config{

	private static final long serialVersionUID = 1L;
	private ImageIcon p0 = new ImageIcon(this.getClass().getResource("night_sky.png"));

	public static void main(String[] args) {
		new MainUI().init();
	}

	public void init() {
		//隐藏菜单栏
		this.setUndecorated(true);
		this.setSize(SCREEN_WIDTH, SCREEN_HEIGHT);
		//添加监听器
		this.addMouseListener(new MouseAdapter() {
			public void mouseClicked(MouseEvent e) {
				//创建匿名对象,传递窗口(this)参数
				//启动线程
				new Thread(new ParticleControl(MainUI.this)).start();
				//移除监听器
				MainUI.this.removeMouseListener(this);
			}
		});
		this.setVisible(true);
	}
	//绘制初始背景
	public void paint(Graphics g) {
		super.paint(g);
		g.drawImage(p0.getImage(), 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, null);
	}
}

粒子控制

package com.Liao.Fireworks0728v0;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.Random;
import javax.swing.ImageIcon;
import javax.swing.JFrame;

public class ParticleControl implements Runnable, Config {
	private JFrame jf;
	private ImageIcon p0 = new ImageIcon(this.getClass().getResource("night_sky.png"));// 背景图片
	private BufferedImage image = new BufferedImage(SCREEN_WIDTH, SCREEN_HEIGHT, BufferedImage.TYPE_INT_RGB);
	private Graphics bg = image.getGraphics();
	private ArrayList<Particle> plist = new ArrayList<Particle>();
	private Sound sound = new Sound();
	private Thread thread;
	private int j;// 烟花发数

	public ParticleControl(JFrame jf) {
		super();
		this.jf = jf;
		// 添加音效
		thread = new Thread(sound);
		thread.start();
	}

	public void run() {
		raise();
	}

	// 烟花上升
	public void raise() {
		// 20发
		for (j = 0; j < 20; j++) {
			// 创建粒子(烟花)
			Particle rp = new Particle();
			rp.position = PSTART;
			rp.velocity = VSTART;
			rp.acceleration = ASTART;
			rp.color = new Color(255, 150, 150);
			rp.width = SIZE / 2;
			rp.height = SIZE;
			//设定上升粒子生命周期
			rp.life = 80 + new Random().nextInt(50);
			for (rp.age = 1; rp.age < rp.life; rp.age++) {
				// 粒子位置
				rp.position = rp.position.add(rp.velocity.multiply(DT));
				rp.velocity = rp.velocity.add(rp.acceleration.multiply(DT));
				// 绘制粒子
				bg.setColor(rp.color);
				bg.drawImage(p0.getImage(), 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, null);
				bg.fillOval(rp.getX(), rp.getY(), rp.width, rp.height);
				jf.getGraphics().drawImage(image, 0, 0, null);
				try {
					Thread.sleep(8);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
			// 调用爆炸效果
			bomp(rp);
		}
	}

	// 璀璨烟花
	public void bomp(Particle rp) {
		//设定爆炸粒子生命周期
		rp.life = 40 + new Random().nextInt(30);
		for (rp.age = 1; rp.age < rp.life; rp.age++) {
			for (int i = 0; i < 30; i++) {
				Particle p = new Particle();
				p.position = new Vector_2(rp.getX(), rp.getY());
				p.velocity = new Vector_2(2, -10);
				p.acceleration = particleDirection();
				p.color = new Color(200 + new Random().nextInt(55), (new Random().nextInt(50) + (i + j) * 100) % 255,
						new Random().nextInt(255));
				p.width = SIZE / 3;
				p.height = SIZE / 3;
				plist.add(p);
			}
			bg.drawImage(p0.getImage(), 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, null);
			for (Particle p : plist) {
				// 计算每个粒子的下一位置
				p.position = p.position.add(p.velocity.multiply(DT));
				p.velocity = p.velocity.add(p.acceleration.multiply(DT));
				// 画到缓冲区
				bg.setColor(p.color);
				bg.fillOval(p.getX(), p.getY(), p.width, p.height);
			}
			jf.getGraphics().drawImage(image, 0, 0, null);
			try {
				Thread.sleep(20);
			} catch (Exception ef) {
			}
		}
		plist.clear();
		jf.getGraphics().drawImage(p0.getImage(), 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, null);
		// 关闭音乐
		if (j == 19) {
			sound.setisstop(true);
			sound.getplayer().close();
			//关闭窗口
			jf.dispose();
		}
	}

	// 生成一个随机方向(粒子加速度)
	public static Vector_2 particleDirection() {
		double theta = Math.random() * 2 * Math.PI;
		return new Vector_2(100 + (Math.cos(theta) * 700), 100 + (Math.sin(theta) * 700));
	}
}

音效(需要导入第三方包 jl1.0.1.jar)

package com.Liao.Fireworks0728v0;

import java.io.BufferedInputStream;
import java.io.FileInputStream;
import javazoom.jl.player.Player;

public class Sound implements Runnable {

	private Boolean isstop = false;
	private Player player;

	public void  setisstop(Boolean isstop){
		this.isstop=isstop;
	}
	
	public Player getplayer(){
		return player;
	}

	public void run() {
		while (!isstop) {
			try {
				BufferedInputStream bis = new BufferedInputStream(new FileInputStream("fireworks.mp3"));
				player = new Player(bis);
				player.play();
			} catch (Exception e) {
				System.out.println("进入异常中");
			//	isstop=true;
			//	return;
			}
		}
	}
}

    就这样,一个简单的烟花就制作完成了,当然咱们还可以给烟花增加一些别的特效,后面再做更新。

猜你喜欢

转载自blog.csdn.net/LIAO_7053/article/details/81428117
今日推荐