前言
之前看过一篇文章, 使用 processing 制作烟花特效效果如下
fireworks 网上调查了一圈了, 发现 processing 是一个互动编程软件, java 语言发展而来而且动画效果是跑在 processing 专门的模拟器上 不过好在也有对应的 web 扩展语言, 有 processing.js 和 p5.js processing.js 在 github 上已经好几年没有人维护了, 一些 processing 的特性支持不了为此踩了不少坑, 本文就集中讲解如何用 p5.js 写烟花特效
代码讲解
processing 风格
- function setup() { //processing 初始化设置
- createCanvas(window.innerWidth, window.innerHeight);
- frameRate(50);
- imageMode(CENTER);
- }
- function draw() { // 循环执行, 达成画面渲染效果
- background(0, 0, 40);
- for (var i = 0; i <fireworks.length; i++) {
- fireworks[i].display();
- fireworks[i].update();
- if (fireworks[i].needRemove()) {
- fireworks.splice(i, 1);
- }
- }
- }
烟花效果
- function Fireworks(radius) {
- var num = 512; // 一发烟花里, 有多少个点 (比较吃机器)
- var centerPosition = new p5.Vector(random(width / 8, width * 7 / 8), random(height / 2, height * 4 / 5), random(-100, 100)); // 烟花的中心位置
- var velocity = new p5.Vector(0, -22, 0);
- var accel = new p5.Vector(0, 0.4, 0);
- var img;
- var firePosition = [];
- var cosTheta;
- var sinTheta;
- var phi;
- var colorChange = random(0, 5);
- for (var i = 0; i < num; i++) {
- cosTheta = random(0, 1) * 2 - 1;
- sinTheta = sqrt(1 - cosTheta * cosTheta);
- phi = random(0, 1) * 2 * PI;
- firePosition[i] = new p5.Vector(radius * sinTheta * cos(phi), radius * sinTheta * sin(phi), radius * cosTheta); //1 发烟花里各个点的位置计算
- firePosition[i] = p5.Vector.mult(firePosition[i], 1.12);
- }
- // 调整烟花随机颜色, 使其更亮丽
- if(colorChange>=3.8){
- img=createLight(0.9,random(0.2,0.5),random(0.2,0.5));
- }else if(colorChange>3.2){
- img=createLight(random(0.2,0.5),0.9,random(0.2,0.5));
- }else if(colorChange>2){
- img=createLight(random(0.2,0.5),random(0.2,0.5),0.9);
- } else {
- img=createLight(random(0.5,0.8),random(0.5,0.8),random(0.5,0.8));
- }
- this.display = function () {
- for (var i = 0; i <num; i++) {
- push();
- translate(centerPosition.x, centerPosition.y, centerPosition.z);
- translate(firePosition[i].x, firePosition[i].y, firePosition[i].z);
- blendMode(ADD); // 各个小点(发光源遮罩效果)
- image(img, 0, 0);
- pop();
- firePosition[i] = p5.Vector.mult(firePosition[i], 1.015); // 更新小点 (发光源) 扩散位置
- }
- }
- this.update = function () { // 模拟重力加速度
- radius = dist(0, 0, 0, firePosition[0].x, firePosition[0].y, firePosition[0].z);
- centerPosition.add(velocity);
- velocity.add(accel);
- }
- this.needRemove = function () {
- if (centerPosition.y - radius> height) {
- return true;
- } else {
- return false;
- }
- }
- }
随机发光源图片生成
- function createLight(rPower, gPower, bPower) {
- var side = 64;
- var center = side / 2.0;
- var img = createImage(side, side);
- img.loadPixels();
- for (var y = 0; y < side; y++) {
- for (var x = 0; x < side; x++) {
- var distance = (sq(center - x) + sq(center - y)) / 10.0;
- var r = int((255 * rPower) / distance);
- var g = int((255 * gPower) / distance);
- var b = int((255 * bPower) / distance);
- // img.pixels[x + y * side] = color(r, g, b);
- img.set(y, x, color(r, g, b));
- }
- }
- img.updatePixels();
- return img;
- }
接收键盘和屏幕触碰事件
- function keyPressed() { // 每事件添加一发烟花
- fireworks.push(new Fireworks(80)); //80 为烟花初始半径
- }
- function touchStarted() { // 每事件添加一发烟花
- fireworks.push(new Fireworks(80));
- return false;
- }
- Github
- https://github.com/cangyan/TAV/tree/master/00003_P5_FIREWORKS
来源: http://www.jb51.net/article/136788.htm