一些看似很炫很好看的效果其实可能只需要几行代码,下面由小编给大家用粒子系统做出好看的效果。
效果图就是这样的啦,感觉还不错吧。如果想看烟花,又没条件,那我们也可以为自己献上一场烟火!
相信大家是迫不及待的想要代码了,那么接下来就是干货时间了。
import javax.swing.JFrame;
import javax.swing.JPanel;
public class FireWorksMain extends JPanel {
public static void main(String[] args) {
FireWorksMain fw = new FireWorksMain();
fw.initUI();
}
public void initUI() {
JFrame f = new JFrame();
f.setTitle("烟花");
f.setSize(800, 700);
f.setDefaultCloseOperation(3);
f.add(this);
f.setVisible(true);//初始化窗口界面
FireWorksThread ft = new FireWorksThread(this);
ft.start();//开启线程
FwListener fl=new FwListener(ft);
this.addMouseMotionListener(fl);//鼠标监听事件
}
}
主函数类应尽量简洁,不要什么都往主函数类里面堆。
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
public class FwListener extends MouseAdapter {
FireWorksThread ft;
public FwListener(FireWorksThread ft) {
this.ft = ft;
}
public void mouseDragged(MouseEvent e) {
ft.setStartXY(e.getX(), e.getY());
}
}
鼠标监听事件类,这个也很简单吧。
public class VecT {
public double x, y;
public VecT(double x, double y) {
this.x = x;
this.y = y;
}
// 向量加
public VecT add(VecT p) {
return new VecT(this.x + p.x, this.y + p.y);
}
// 向量乘
public VecT multiply(double f) {
return new VecT(this.x * f, this.y * f);
}
}
这是一个向量类,粒子的所有坐标消息都可以用这个类来处理。
import java.awt.Color;
public class Particle {
//粒子的起点,速度,重力
public VecT position,velocity,acceleration;
public Color color;
public double life,age,start_time;
public int size;
//在界面上绘制时的x,y坐标
public int x,y;
public int getX(){
return (int)position.x;
}
public int getY(){
return (int)position.y;
}
}
这是粒子类,这里面是粒子的各种属性,单独放一个类,以后想修改代码就很简单啦。
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.RenderingHints;
import java.awt.Toolkit;
import java.util.ArrayList;
import javax.swing.JPanel;
public class FireWorksThread extends Thread {
private static JPanel panel;
Graphics g;
// 保存粒子的队列
private ArrayList<Particle> pr = new ArrayList<>();
// 起始位置
private int startX = 300, startY = 500;
public FireWorksThread(JPanel panel) {
this.panel = panel;
}
public void setStartXY(int x, int y) {
this.startX = x;
this.startY = y;
}
public void run() {
// 时间增量
double dt = 0.1d;
while (true) {
// 画背景
g = panel.getGraphics();
// 生成粒子放入链表
Particle tp = new Particle();
tp.position = new VecT(startX, startY);
tp.velocity = new VecT(10, -20);// 速度向量
tp.acceleration = sampleDirection();
tp.life = 30;
tp.age = 1;
tp.color = new Color(255, 0, 255);
tp.size = 12;
pr.add(tp);
// 链表中的粒子画到缓冲区,再画到界面上
Image image = panel.createImage(panel.getWidth(), panel.getHeight());
Graphics2D bg = (Graphics2D) image.getGraphics();
bg.setColor(Color.black);
bg.fillRect(0, 0, panel.getWidth(), panel.getHeight());// 画背景
bg.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
for (int i = 0; i < pr.size(); ++i) {
Particle p = pr.get(i);
// 1.判断粒子的生命是否到期,到期后,从链表中移除
p.age += dt;
if (p.age >= p.life) {
pr.remove(i);
}
// 2.计算每个粒子的下一个位置
int r = p.color.getRGB();
r -= 1000;
Color c = new Color(r);
p.color = c;
// 判断是否碰撞到墙
isrebound(p);
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.size, p.size);
}
// 将缓冲图片画到面板上
g.drawImage(image, 0, 0, null);
try {
Thread.sleep(10);
} catch (Exception ef) {
}
}
}
// 让粒子碰到墙后反弹
public static void isrebound(Particle p) {
if (p.getX() <= 0 || p.getX() >= panel.getWidth())
p.velocity.x *= -1;
if (p.getY() <= 0)
p.velocity.y *= -1;
}
// 生成一个随机方向
public static VecT sampleDirection() {
double theta = Math.random() * 2 * Math.PI;
return new VecT((Math.cos(theta)), (Math.sin(theta)));
}
}
好啦,这里就是全部的代码了,大家可以去炫炫技啦。
当然还要能用这个改造各种好看的效果出来,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,
比如,小编将粒子改成了樱花,那么会发生什么呢?
就是这样了,是不是感觉到了樱花浪漫的气氛呢?
图片也送给大家使用啦。
什么?想要变颜色?有想象力是好事,那就请看下回分解啦!