【项目介绍】
【代码展示】
一、类介绍
- 烟花类 包含烟花串对象数组(同时向数组中添加10~50个烟花串对象,每个烟花串起始点相同)、色调(每簇烟花的色相是相同的)
class Firework
{
constructor(x,y){
this.H = random(0,239); //色调
this.stringarray=new Array();
for(var i=0; i<random(10,50); i++)
this.stringarray.push(new FireworkString(x,y));
}
drawFireworkString(){
this.stringarray.forEach((tmp)=>{ //遍历粒子串数组并绘制
tmp.drawFireworkParticle(this.H);
})
}
}
- 烟花串类 包含一个起始点 FireworkParticle(每串粒子的饱和度和亮度相同,不同串则不同)、可见的烟花粒子队列 Visible(同时压起始点入队)
class FireworkString
{
constructor(firstX,firstY){
this.S = random(0,240); //饱和度
this.B = random(0,240); //亮度
this.len=random(5,15); //控制烟花串长度
//烟花粒子初始化
this.fireworkparticle=new FireworkParticle(firstX,firstY,random(5,15),
50,10);
this.Visible=new Array();
this.Visible.push(this.fireworkparticle);
}
drawFireworkParticle(H){
this.fireworkparticle.update(); //更新粒子
tmp=this.fireworkparticle;
this.Visible.push(new FireworkParticle(tmp.x, tmp.y, tmp.radius,
tmp.alphaSpeed, tmp.initSpeed)); //入队
this.Visible.forEach((tmp)=>{ //遍历绘制
if(!tmp.deleteCheck()){
//tmp.blinking();
tmp.draw(H,this.S,this.B);
}
})
if(this.Visible.length>this.len) this.Visible.shift(); //判断出队
}
}
- 烟花粒子类 包含坐标、半径、透明度递减速度、初始速度。颜色模式为HSB,初始化moveXY、alpha。
update() 用于更新每串烟花粒子下一个粒子的位置并变形外观
draw() 用于先示该粒子(在alpha或radius降为0、该粒子不在粒子队列的情况下,是不会显示的)
//烟花粒子
class FireworkParticle
{
constructor(x, y, //坐标
radius, //半径
alphaSpeed, //透明速度
initSpeed) { //初始速度
colorMode(HSB, 255);
noStroke(); //取消描边
this.x = x; this.y = y;
this.radius = radius;
this.alpha = 200;
this.alphaSpeed = alphaSpeed;
//一开始即确定水平与垂直方向初速度
this.moveX = random(-initSpeed, initSpeed);
this.moveY = random(-initSpeed, initSpeed);
}
update() {
//移动
this.moveX = this.moveX * AirF;
this.moveY = this.moveY * AirF + Gravity;
this.x = this.x + this.moveX;
this.y = this.y + this.moveY;
//变形
this.alpha = this.alpha - this.alphaSpeed;
this.radius = this.radius - 0.3;
}
draw(H,S,B) {
fill(H, S, B, this.alpha);
ellipse(this.x, this.y, this.radius, this.radius);
}
deleteCheck() {
if (this.x < 0 || this.x > width || this.y > height || this.radius < 0) {
return true;
}
}
}
二、主函数
画板大小为1000*1000,背景为黑色,鼠标每点击一次,创建一个烟花对象并压入烟花对象数组中。每帧运行时清空画板填充黑色背景,并遍历烟花对象数组,为每一簇烟花绘制其烟花串。
const Gravity=0.5; //重力
const AirF=1; //空气阻率
var FireworkArray = new Array();
var tmp;
function setup(){ createCanvas(1000, 1000); }
function draw(){
background(0);
FireworkArray.forEach((tmp)=>{ //遍历烟花数组并绘制
tmp.drawFireworkString();
})
}
//鼠标点击时,在点击处创建烟花
function mouseClicked(){
var firework=new Firework(mouseX,mouseY);
FireworkArray.push(firework);
}
每一个烟花串又会绘制其烟花粒子
drawFireworkString(){
this.stringarray.forEach((tmp)=>{ //遍历粒子串数组并绘制
tmp.drawFireworkParticle(this.H);
})
}
绘制烟花粒子时,先更新粒子并压入队列,遍历队列绘制每一个粒子(半径为0以及不在画板的粒子不画),最后判断队列是否过长(过长就弹出队首粒子)
drawFireworkParticle(H){
this.fireworkparticle.update(); //更新粒子
tmp=this.fireworkparticle;
this.Visible.push(new FireworkParticle(tmp.x, tmp.y, tmp.radius,
tmp.blinkingSpeed, tmp.initSpeed)); //入队
this.Visible.forEach((tmp)=>{ //遍历绘制
if(!tmp.deleteCheck()){
//tmp.blinking();
tmp.draw(H,this.S,this.B);
}
})
if(this.Visible.length>this.len) this.Visible.shift(); //判断出队
}