gpt4 book ai didi

javascript - 如何在 JavaScript 中为某些对象创建残像

转载 作者:行者123 更新时间:2023-12-05 00:36:56 28 4
gpt4 key购买 nike

我正在使用 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);

}

}
最后,firework.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;

}

}
没有残像提供的轨迹,烟花看起来一点也不像火焰作品,但我还实现了一个我创建的 FPS 监视器,它也由于背景功能而模糊(这种效果是不需要的。)
关于后台功能的更多信息:
我正在使用语法: background(v1, v2, v3, [a]) v1、v2 和 v3 是 HSB 变量。可选变量 [a] 定义为:背景相对于当前颜色范围的不透明度(默认为 0-255)
完整后台网址: https://p5js.org/reference/#/p5/background
问题
我如何让烟花看起来一样,而不影响 Canvas 上的其他东西?比如项目中的FPS监视器可以通过鼠标拖动来移动,但它也有那种来自背景功能的残影效果。我希望烟花保持不变,但渲染的其他任何东西都需要“不”模糊。
非常感谢任何帮助。

最佳答案

您可以使用 createGraphics() 在 p5.js 中使用单独的“层” .
例如,烟花类可以持有它的 p5.Graphics它可以用来渲染效果的实例,然后在主草图的draw()中你会调用image() ,通过 p5.Graphics实例(就好像它是一个图像)显示到主 p5.js Canvas 中。
(题外话,您可以研究对象池以重置/重用“死”粒子
而不是删除/重新分配新的)
更新
似乎有效,这是我的意思的一种方法:

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 - 如何在 JavaScript 中为某些对象创建残像,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72175531/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com