java 粒子系统_Java粒子系统(烟火篇)
用好粒子系統,自己也可以自制一場煙火!
比如說這樣的,這就是一個慢慢優化的過程。
下面就上代碼大家仔細體會一下吧
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.setLocationRelativeTo(null);
f.add(this);
f.setVisible(true);
FireWorksThread ft = new FireWorksThread(this);
ft.start();
}
}
主函數類都很熟悉了吧
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;
}
}
粒子類也是一樣的
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.AlphaComposite;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.RenderingHints;
import java.util.ArrayList;
import javax.swing.JPanel;
public class Bomb {
// Bomb的屬性
// 粒子的起點,速度,重力
public VecT position, velocity, acceleration;
public double life, age, start_time;
public int size;
public int x, y;
public float alpha;
public int getX() {
return (int) position.x;
}
public int getY() {
return (int) position.y;
}
public Color Bombcolor;
// 創建粒子鏈表
private ArrayListpr = new ArrayList<>();
// 創建顏色
private Color color1[] = { Color.BLUE.brighter(), Color.CYAN.brighter(), Color.GRAY.brighter(),
Color.lightGray.brighter(), Color.ORANGE.brighter(), Color.RED.brighter(), Color.ORANGE.brighter(),
Color.magenta.brighter(), Color.YELLOW.brighter() };
private Color color2[] = { new Color(0, 200, 20), new Color(250, 40, 40), new Color(20, 250, 60),
new Color(110, 10, 110), new Color(10, 100, 130), new Color(250, 0, 250), new Color(0, 100, 200),
new Color(100, 80, 250), new Color(80, 0, 0),new Color(0,0,100),new Color(0,50,200),new Color(11,151,10) };
private int colornum1 = -1, colornum2 = -1;
// 畫分散
public void drawscatter(Graphics g, double dt, double x, double y, JPanel panel) {
if (colornum1 == -1 || colornum2 == -1) {
colornum1 = (int) (Math.random() * (color1.length - 1));
colornum2 = (int) (Math.random() * (color2.length - 1));
//colornum2 = (color2.length - 1);
}
if (pr.size() < 540) {
for (int i = 0; i < 300; ++i) {
Particle tp = new Particle();
tp.position = new VecT(x, y);
tp.velocity = sampleDirectionv2().multiply(1 - (double) (i / 30) / (double) 10);// 速度向量
tp.acceleration = tp.velocity.multiply(0.1);
tp.life = 7;
tp.age = 1;
tp.color = color1[colornum1];
tp.size = (int) (4 + Math.random() * 3);
pr.add(tp);
}
for (int i = 0; i < 300; ++i) {
Particle tp = new Particle();
tp.position = new VecT(x, y);
tp.velocity = sampleDirectionv1().multiply(1 - (double) (i / 30) / (double) 20);// 速度向量
tp.acceleration = tp.velocity.multiply(0.1);
tp.life = 7;
tp.age = 1;
tp.color = color2[colornum2];
tp.size = (int) (4 + Math.random() * 3);
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.判斷粒子的生命是否到期,到期后,從鏈表中移除
if (p.age == 1)
alpha = 1f;
p.age += dt;
if (p.age >= p.life) {
pr.remove(i);
}
// 2.計算每個粒子的下一個位置
p.position = p.position.add(p.velocity.multiply(dt));
p.velocity = p.velocity.add(p.acceleration.multiply(dt));
alpha -= 0.00019 / (double) p.life;
bg.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, alpha));// 透明度
// 畫到緩沖區
bg.setColor(p.color);
bg.fillOval(p.getX(), p.getY(), p.size, p.size);
}
// 將緩沖圖片畫到面板上
g.drawImage(image, 0, 0, null);
}
// 生成一個隨機方向煙花的
public static VecT sampleDirectionv2() {
double theta = Math.random() * 4 * Math.PI;
return new VecT((12 * Math.cos(theta)), (12 * Math.sin(theta)));
}
// 生成一個隨機方向速度
public static VecT sampleDirectionv1() {
double theta = Math.random() * 4 * Math.PI;
return new VecT((20 * Math.cos(theta)), 20 * (Math.sin(theta)));
}
}
創建一個bomb類爆炸效果的方法都在里面
import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.RenderingHints;
import java.util.ArrayList;
import javax.swing.JPanel;
public class FireWorksThread extends Thread {
private static JPanel panel;
Graphics2D g;
// 保存粒子的隊列
private ArrayListbo = new ArrayList<>();
// 起始位置
private int startX, startY = 600;
private boolean isadd = true;
float alpha; // 透明度
public FireWorksThread(JPanel panel) {
this.panel = panel;
}
public void run() {
// 時間增量
double dt = 0.1d;
g = (Graphics2D) panel.getGraphics();
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
while (true) {
// 判斷是否增加Bomb, 生成Bomb放入鏈表
if (isadd == true) {
Bomb bb = new Bomb();
startX = (int) (Math.random() * (panel.getWidth() - 200) + 80);
if (startX > panel.getWidth() - 80) {
startX = panel.getWidth() - 80;
}
bb.position = new VecT(startX, startY);
bb.velocity = new VecT(0, -35);// 速度向量
bb.acceleration = new VecT(0, 1);
bb.life = 16 + Math.random() * 6;
bb.age = 1;
bb.Bombcolor = new Color(255, 255, 255).brighter();
bb.size = 24;
bo.add(bb);
}
for (int i = 0; i < bo.size(); ++i) {
Bomb b = bo.get(i);
if (b.age < b.life) {
this.drawrise(g, dt, b);
isadd = false;
} else {
b.age += dt;
b.drawscatter(g, dt, b.getX(), b.getY(), panel);
}
if (b.age > b.life + 6) {
bo.remove(i);
isadd = true;
}
}
try {
Thread.sleep(10);
} catch (Exception ef) {
}
}
}
// 畫上升
public void drawrise(Graphics2D g, double dt, Bomb b) {
Image image = panel.createImage(panel.getWidth(), panel.getHeight());
Graphics2D bg = (Graphics2D) image.getGraphics();
if (b.age == 1)
alpha = 1;
bg.setColor(Color.black.brighter());
bg.fillRect(0, 0, panel.getWidth(), panel.getHeight());// 畫背景
alpha -= 0.09 / (double) b.life;
bg.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, alpha));// 透明度
bg.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);// 抗鋸齒
b.position = b.position.add(b.velocity.multiply(dt));
b.velocity = b.velocity.add(b.acceleration.multiply(dt));
b.age += dt;
b.Bombcolor = new Color(255, 255, 255);
bg.setColor(b.Bombcolor);
bg.fillOval(b.getX(), b.getY(), b.size, b.size);
g.drawImage(image, 0, 0, null);
}
}
線程類,里面也有個炸彈上升的方法!
好啦,代碼可能不是很精簡,很多地方可以優化,也可以改造成很多更加好看的效果,
大家可以多多嘗試!
總結
以上是生活随笔為你收集整理的java 粒子系统_Java粒子系统(烟火篇)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 看了一个月c能学java_学过一点C语言
- 下一篇: 常见的计算机系统结构不包括,计算机系统结