我正在用p5制作烟花表演.js库(尽管我怀疑这会影响答案).我目前的程序使用p5.js背景功能可以为整个项目创建后像.你可以在这里查看该项目:https://editor.p5js.org/KoderM/sketches/WsluEg00h

但您也可以在此处查看代码:


let particles, FPS;

function setup() {
  
  createCanvas(1000, 800);
  
  background(220);
  
  particles = [];
  
  FPS = new FPSMonitor(50, 50);
  
}

function draw() {
  
  colorMode(RGB);
  
  background(0, 0, 0, 25);
  
  for(let p in particles){
    
    if(particles[p].isDead()){
      
      particles.splice(p, 1);
      
      continue;
      
    }
    
    particles[p].update();
    
  }
  
  FPS.update();
  
}

function mousePressed(){
  
  particles.push(new firework(mouseX, mouseY, random(0, 255)));
  particles[particles.length-1].velocity = p5.Vector.random2D();
  particles[particles.length-1].velocity.mult(random(0.5, 10));
  
}


class FPSMonitor {
  
  constructor(x, y){
    
    this.x = x;
    this.y = y;
    
    this.size = 100;
    
    this.delay = millis();
    
    this.mouse = [0, 0];
    
  }
  
  update(){
    
    this.checkMouse();
    
    if(this.mouse[0] !== 0){
      
      this.x = mouseX - this.mouse[0];
      this.y = mouseY - this.mouse[1];
      
    }
    
    textAlign(LEFT, TOP);
    textSize(this.size/6);
    rectMode(CORNER);
    strokeWeight(3);
    stroke("red");
    fill("white");
    
    rect(this.x, this.y, this.size*1.2, this.size);
    
    strokeWeight(4);
    stroke("black");
    
    text("FPS: " + round(1/(millis()-this.delay)*1000, 3), this.x+5, this.y+5);
    
    text("Average FPS:", this.x+5, this.y+25);
    text(round(frameCount/millis()*1000, 3), this.x+5, this.y+48);
    
    text("MS: " + round(millis()-this.delay), this.x+5, this.y+72);
    
    this.delay = millis();
    
  }
  
  checkMouse(){
    
    if(mouseIsPressed && this.mouse[0] !== 0){
      
      return;
      
    }
    
    if(this.x < mouseX && (this.x + this.size) > mouseX && 
       this.y < mouseY && (this.y + this.size) > mouseY && mouseIsPressed){
      
      if(this.mouse[0] == 0){
      
        this.mouse = [ mouseX - this.x, mouseY - this.y ]
      
      }
      
      return;
      
    }
      
    this.mouse = [0, 0];
    
  }
  
}

微粒js:


class particle {
  
  constructor(x, y, hue, gravity, life, weight, renderFunction){
    
    if(!hue){ throw new TypeError(this + " : hue is not defined") }
    
    this.defaults = {
      
      x: 0,
      y: 0,
      gravity: createVector(0, 0),
      life: 100,
      weight: 1,
      renderFunction: (self) => {colorMode(HSB);strokeWeight(2);stroke(this.hue, 255, 255, this.life/this.maxLife);point(this.position.x, this.position.y)}
      
    }
    
    this.position = x && y ? createVector(x, y) : createVector(this.defaults.x, this.defaults.y);
    
    this.gravity = gravity || this.defaults.gravity;
    
    this.life = life || this.defaults.life;
    
    this.maxLife = this.life;
    
    this.acceleration = createVector(0, 0);
    
    this.velocity = createVector(0, 0);
    
    this.weight = weight || this.defaults.weight;
    
    this.renderFunction = renderFunction || this.defaults.renderFunction;
    
    this.hue = hue;
    
    this.otherInfo = {
      
      mouseAtStart: createVector(mouseX, mouseY),
      
    }
    
  }
  
  isDead(){
    
    return this.life < 0;
    
  }
  
  applyForce(force){
    
    this.acceleration.add(force);
    
  }
  
  update(){
    
    this.life--;
    
    this.acceleration.add(this.gravity);
    this.velocity.add(this.acceleration);
    this.position.add(this.velocity);
    this.velocity.mult(this.weight*0.96>1?0.96:this.weight*0.96);
    this.acceleration.mult(0.1);
    
    this.renderFunction(this);
    
  }
  
}

最后是烟火.js:


class firework {
  
  constructor(x, y, hue){
    
    this.renderFunction = self => {
      
      colorMode(HSB);
    
      strokeWeight(3);
      stroke(self.hue, 255, 255, (self.life+self.maxLife*0.5)/self.maxLife)

      //line(self.otherInfo.mouseAtStart.x, self.otherInfo.mouseAtStart.y, self.position.x, self.position.y);

      point(self.position.x, self.position.y);
      
    };
    
    this.explodeRenderFunction = self => {
      
      colorMode(HSB);
    
      strokeWeight(3);
      stroke(self.hue, 255, 255, self.life/self.maxLife)

      //line(self.otherInfo.mouseAtStart.x, self.otherInfo.mouseAtStart.y, self.position.x, self.position.y);

      point(self.position.x, self.position.y);
      
    }
    
    this.particle = new particle(x, y, hue, createVector(0, 0.1), height/53.3 * 4, 1, this.renderFunction);
    
    this.particle.applyForce(createVector(random(-3, 3), random(height/-53.3, height/-43.3)));
    
    this.explodeParticles = [];
    
    this.exploded = false;
    
    this.hue = hue;
    
  }
  
  update(){
    
    this.particle.update();
    
    if(this.particle.isDead() && !this.exploded){
      
      this.particle.renderFunction = (self) => {};
      
      this.exploded = true;
  
      for(let p = 0; p < 500; p++){

        this.explodeParticles.push(new particle(this.particle.position.x, this.particle.position.y, this.hue, createVector(0, 0.1), 100, 1, this.explodeRenderFunction));
        this.explodeParticles[this.explodeParticles.length-1].velocity = p5.Vector.random2D();
        this.explodeParticles[this.explodeParticles.length-1].velocity.mult(random(0.5, 10));

      }
      
    }
    
    if(this.exploded){
      
      for(let p in this.explodeParticles){
    
        if(this.explodeParticles[p].isDead()){

          this.explodeParticles.splice(p, 1);

          continue;

        }

        this.explodeParticles[p].update();

      }
      
    }
    
  }
  
  isDead(){
    
    return this.explodeParticles.length == 0 && this.exploded;
    
  }
  
}

如果没有后像提供的轨迹,烟花看起来一点也不像fire works,但我还实现了一个我创建的FPS监视器,它也会因为背景功能而模糊(这种效果是不需要的)

关于后台函数的更多信息:

我使用的语法是:background(v1, v2, v3, [a])v1、v2和v3是HSB变量.可选变量[a]定义为:相对于当前 colored颜色 范围的背景不透明度(默认值为0-255)

完整背景网站:https://p5js.org/reference/#/p5/background

THE QUESTION

我如何让烟花看起来一样,而不影响画布上的其他东西?例如,项目中的FPS监视器可以通过拖动鼠标来移动,但它也具有来自背景功能的后像效果.我希望烟火保持不变,但任何其他渲染都需要"不"模糊.

非常感谢你的帮助.

推荐答案

你可以在p5中使用单独的"层".js使用createGraphics().

(在主题之外,您可以研究对象池以重置/重用"死"粒子.)

Update

似乎有效,以下是我的意思:

let particles, FPS;
// independent layers to render graphics into
let particlesLayer;
let fpsLayer;

function setup() {
  
  createCanvas(1000, 800);
  
  background(0);
  
  particles = [];
  
  FPS = new FPSMonitor(50, 50);
  // particles will take up the whole sketch
  particlesLayer = createGraphics(width, height);
  // we can get away with a smaller frame buffer for the FPS meter
  fpsLayer = createGraphics(256, 216);
  
}

function draw() {

  particlesLayer.colorMode(RGB);
  
  particlesLayer.background(0, 0, 0, 25);
  
  for(let p in particles){
    
    if(particles[p].isDead()){
      
      particles.splice(p, 1);
      
      continue;
      
    }
    
    particles[p].update();
    
  }
  // render the fireworks layers into the main sketch
  image(particlesLayer, 0, 0);
  // pass the layer to render the fps meter into and display it
  FPS.update(fpsLayer);
  
}

function mousePressed(){
  // pass the particles layer to each firework instance to render into
  particles.push(new firework(mouseX, mouseY, random(0, 255), particlesLayer));
  particles[particles.length-1].velocity = p5.Vector.random2D();
  particles[particles.length-1].velocity.mult(random(0.5, 10));
  
}

function mouseDragged(){
  FPS.x = mouseX - FPS.size * 0.5;
  FPS.y = mouseY - FPS.size * 0.5;
}


class FPSMonitor {
  
  constructor(x, y){
    
    this.x = x;
    this.y = y;
    
    this.size = 100;
    
    this.delay = millis();
  }
  
  update(g){
    
    g.textAlign(LEFT, TOP);
    g.textSize(this.size/6);
    g.rectMode(CORNER);
    g.strokeWeight(3);
    g.stroke("red");
    g.fill("white");
    
    g.rect(0, 0, this.size * 1.2, this.size);
    g.noStroke();
    g.fill(0);
    
    g.text("FPS: " + round(1/(millis()-this.delay)*1000, 3), 5, 5);
    
    g.text("Average FPS:", 5, 25);
    g.text(round(frameCount/millis()*1000, 3), 5, 48);
    
    g.text("MS: " + round(millis()-this.delay), 5, 72);
    
    this.delay = millis();
    
    // render the graphics
    image(g, this.x, this.y);
  }
  
}

class particle {
  
  constructor(x, y, hue, gravity, life, weight, renderFunction){
    
    if(!hue){ throw new TypeError(this + " : hue is not defined") }
    
    this.defaults = {
      
      x: 0,
      y: 0,
      gravity: createVector(0, 0),
      life: 100,
      weight: 1,
      renderFunction: (self) => {colorMode(HSB);strokeWeight(2);stroke(this.hue, 255, 255, this.life/this.maxLife);point(this.position.x, this.position.y)}
      
    }
    
    this.position = x && y ? createVector(x, y) : createVector(this.defaults.x, this.defaults.y);
    
    this.gravity = gravity || this.defaults.gravity;
    
    this.life = life || this.defaults.life;
    
    this.maxLife = this.life;
    
    this.acceleration = createVector(0, 0);
    
    this.velocity = createVector(0, 0);
    
    this.weight = weight || this.defaults.weight;
    
    this.renderFunction = renderFunction || this.defaults.renderFunction;
    
    this.hue = hue;
    
    this.otherInfo = {
      
      mouseAtStart: createVector(mouseX, mouseY),
      
    }
    
  }
  
  isDead(){
    
    return this.life < 0;
    
  }
  
  applyForce(force){
    
    this.acceleration.add(force);
    
  }
  
  update(){
    
    this.life--;
    
    this.acceleration.add(this.gravity);
    this.velocity.add(this.acceleration);
    this.position.add(this.velocity);
    this.velocity.mult(this.weight*0.96>1?0.96:this.weight*0.96);
    this.acceleration.mult(0.1);
    
    this.renderFunction(this);
    
  }
  
}

class firework {
  
  constructor(x, y, hue, graphicsLayer){
    // store the reference to the same particle layers
    this.g = graphicsLayer;
    this.renderFunction = self => {
      // use the layer to draw into, not the global p5.js graphics
      this.g.colorMode(HSB);
    
      this.g.strokeWeight(3);
      this.g.stroke(self.hue, 255, 255, (self.life+self.maxLife*0.5)/self.maxLife)

      //line(self.otherInfo.mouseAtStart.x, self.otherInfo.mouseAtStart.y, self.position.x, self.position.y);

      this.g.point(self.position.x, self.position.y);
      
    };
    
    this.explodeRenderFunction = self => {
      
      this.g.colorMode(HSB);
    
      this.g.strokeWeight(3);
      this.g.stroke(self.hue, 255, 255, self.life/self.maxLife)

      //line(self.otherInfo.mouseAtStart.x, self.otherInfo.mouseAtStart.y, self.position.x, self.position.y);

      this.g.point(self.position.x, self.position.y);
      
    }
    
    this.particle = new particle(x, y, hue, createVector(0, 0.1), height/53.3 * 4, 1, this.renderFunction);
    
    this.particle.applyForce(createVector(random(-3, 3), random(height/-53.3, height/-43.3)));
    
    this.explodeParticles = [];
    
    this.exploded = false;
    
    this.hue = hue;
    
  }
  
  update(){
    
    this.particle.update();
    
    if(this.particle.isDead() && !this.exploded){
      
      this.particle.renderFunction = (self) => {};
      
      this.exploded = true;
  
      for(let p = 0; p < 500; p++){

        this.explodeParticles.push(new particle(this.particle.position.x, this.particle.position.y, this.hue, createVector(0, 0.1), 100, 1, this.explodeRenderFunction));
        this.explodeParticles[this.explodeParticles.length-1].velocity = p5.Vector.random2D();
        this.explodeParticles[this.explodeParticles.length-1].velocity.mult(random(0.5, 10));

      }
      
    }
    
    if(this.exploded){
      
      for(let p in this.explodeParticles){
    
        if(this.explodeParticles[p].isDead()){

          this.explodeParticles.splice(p, 1);

          continue;

        }

        this.explodeParticles[p].update();

      }
      
    }
    
  }
  
  isDead(){
    
    return this.explodeParticles.length == 0 && this.exploded;
    
  }
  
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.1/p5.min.js"></script>

下面是一个截图:

fps meter rendered on top of a particle simulation of fireworks with trails (faded background)

烟花有痕迹,但文字清晰(没有模糊/痕迹)

Javascript相关问答推荐

将json数组项转换为js中的扁平

使用javascript将Plotly Expandable Sparkline转换为HighCharter Plot在bslib卡中

我在我的Java代码中遇到了问题,代码的一部分看不到先前定义的对象

如何在bslib nav_insert之后更改导航标签的CSS类和样式?

Websocket错误—有一个或多个保留位开启:reserved1 = 1,reserved2 = 0,reserved3 = 0

Chart.js-显示值应该在其中的引用区域

如何在Angular17 APP中全局设置AXIOS

扩展类型的联合被解析为基类型

VSCode中出现随机行

expo 联系人:如果联系人的状态被拒绝,则请求访问联系人的权限

将范围 Select 器添加到HighChart面积图

Django导入问题,无法导入我的应用程序,但我已在设置中安装了它

bootstrap S JS赢得了REACT中的函数/加载

如何检测当前是否没有按下键盘上的键?

如何处理不带参数的redux thunk payloadCreator回调函数?

使用Java脚本替换字符串中的小文本格式hashtag

JSON Web令牌(JWT)错误:RSA密钥对的签名无效

带元素数组的Mongo聚合

JQuery-无法 Select 使用elementor添加的元素的值

2.0.0-dev quill拖动文本不起作用如何使其拖动文本