一些看似很炫很好看的效果其實可能隻需要幾行代碼,下面由小編給大家用粒子系統做出好看的效果。
效果圖就是這樣的啦,感覺還不錯吧。如果想看煙花,又沒條件,那我們也可以為自己獻上一場煙火!
相信大家是迫不及待的想要代碼了,那麼接下來就是幹貨時間了。
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)));
}
}
好啦,這裡就是全部的代碼了,大家可以去炫炫技啦。
當然還要能用這個改造各種好看的效果出來,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,
比如,小編将粒子改成了櫻花,那麼會發生什麼呢?
就是這樣了,是不是感覺到了櫻花浪漫的氣氛呢?
圖檔也送給大家使用啦。
什麼?想要變顔色?有想象力是好事,那就請看下回分解啦!