gpt4 book ai didi

javascript - 如何在 JavaScript/jQuery 中为粒子系统重用数组中的对象?

转载 作者:行者123 更新时间:2023-12-01 01:46:10 25 4
gpt4 key购买 nike

我正在为 Canvas 游戏构建实体系统。这从一个简单的粒子发射器/更新器开始,我正在对其进行更改以适应多粒子/实体生成器。虽然我通常可以使用 JavaScript/jQuery,但由于涉及数组,我遇到了经验的限制,并且非常乐意接受以下方面的任何帮助:

当我需要一个新的粒子/实体时,我当前的系统会调用一个函数将对象插入一个数组,该数组包含用于实体更新的变量。

然后更新函数在数组上运行 for 循环,检查类型变量以更新粒子(位置/颜色/等...)。以前我会根据某些条件 [array.splice] 粒子。当我需要更多粒子/实体时,我会推送新粒子。

我想在这里实现的是:

在 makeParticle 函数中,检查粒子数组中是否有任何“死”粒子,如果有可用的,则重用它们,如果没有,则推送一个新粒子。为此,我创建了一个 molecularAlive var 作为标志。

var particles = [];
var playing = false;

function mousePressed(event) {
playing = !playing;
}

if(playing) {
makeParticle(1, 200, 200, 10, "blueFlame");
makeParticle(1, 300, 200, 10, "redFlame");
}

function makeParticle(numParticles, xPos, yPos, pRadius, pType) {
var i;
for (i = 0; i < numParticles; i++) {
var p = {
type : pType,
x : xPos,
y : yPos,
xVel : random(-0.5, 0.5),
yVel : random(-1, -3),
particleAlive : true,
particleRender : true,
size : pRadius
}; // close var P

particles.push(p);

// instead of pushing fresh particles all the time I would like the function, here, to check for free objects in the array

} // close for loop

} // close function makeParticle

function runtime() {

for(var i=0; i<particles.length; i++) {

var p = particles[i];
var thisType = p.type;

switch (thisType) {

case "blueFlame":
c.fillStyle = rgb(100,100,255);
c.fillCircle(p.x,p.y,p.size);
p.x += p.xVel;
p.y += p.yVel;
p.size*=0.9;

if (particles.size < 0.5) {
particleAlive = false;
particleRender = false;
} // close if
break;

case "redFlame":
c.fillStyle = rgb(255,100,100);
c.fillCircle(p.x,p.y,p.size);
p.x -= p.xVel;
p.y -= p.yVel;
p.size*=0.95;
if (particles.size < 0.5) {
particleAlive = false;
particleRender = false;
} // close if
break;
} // close switch
} // close function runtime

我已经找到了相关问题的先前答案,但我无法让它在 makeParticle 函数中工作,例如如何将 p 的属性分配给粒子[j]:

var particleUseOldOrNew = function() {

for (var j = 0, len = particles.length; j < len; j++) {

if (particles[j].particleAlive === false)
// particles[j] = p;
return particle[j];
}
return null; // No dead particles found, create new "particles.push(p);" perhaps?
}

最佳答案

我个人对此事的看法是,如果你要制作一个新粒子,它应该是一个新对象,而不是“重新使用”属性已更改的旧粒子。每个新对象都应该有一个唯一的标识符,因此如果您需要跟踪它们(出于开发目的、调试或以后重用),这很容易做到。或者至少保留一个计数器,记录您重复使用粒子对象来表示"new"粒子的次数!尽管我猜想如果您发现“重用”可以提高性能(是吗?),那就是正确的方法。

无论如何,已经足够武断了,这就是我将如何做你所要求的事情(我认为速度是你主要关心的问题,所以我只用原生 JS 做到了这一点):

var particles = [];

//Function to create brand spanking new particle
function makeNewParticle(xPos, yPos, pRadius, pType){
return {
type : pType,
x : xPos,
y : yPos,
xVel : random(-0.5, 0.5),
yVel : random(-1, -3),
particleAlive : true,
particleRender : true,
size : pRadius
};
};



//Function to change the properties of an old particle to make a psuedo-new particle (seriously, why do you want to do this?)
function changeExistingParticle(existing, xPos, yPos, pRadius, pType){
existing.x = xPos;
existing.y = yPos;
existing.size = pRadius;
existing.type = pType;
return existing;
};



//Figure out the keys of dead particles in the particles[] array
function getDeadParticleKeys() {
var keys = [];
for(var p = 0; P < particles.length; p++) {
if (!particles[p].particleAlive) {
keys.push(p);
}
}
};



function makeParticle(numParticles, xPos, yPos, pRadius, pType) {
var d, i, deadParticles;

//Grab the "dead" particle keys
deadParticleKeys = getDeadParticleKeys();
numParticles -= deadParticleKeys.length;

//Replace each dead particle with a "live" one at a specified key
for (d = 0; d < deadParticleKeys.length; d++) {
particles[ deadParticleKeys[d] ] = changeExistingParticle(particles[ deadParticleKeys[d] ], xPos, yPos, pRadius, pType)
}

//If we had more particles than there were dead spaces available, add to the array
for (i = 0; i < numParticles; i++) {
particles.push( makeNewParticle(xPos, yPos, pRadius, pType) );
}
};

现在,我建议这样做:放弃这个想法或“重复使用”粒子,为每个粒子创建一个单独的构造函数(如果您将来向粒子添加方法,这将有很大帮助),然后报废每添加一个粒子:

//Make a constructor for a particle
var Particle = function(props){
if (typeof props === 'function') {
props = props();
}
this.type = props.type;
this.x = props.x;
this.y = props.y;
this.size = props.size;
};
Paticle.prototype.particleAlive = true;
Paticle.prototype.particleRender = true;

//Global particles list
var particles = [];

//Remove all dead element from a ParticleList
particles.clean = function(){
var p, keys;
for (p = this.length; p >= 0; p--) {
if (!p.particleAlive) {
this.splice(p, 1);
}
}
};

//Method for adding x amount of new particles - if num parameter isn't provided, just assume it to be 1
particles.add = function(props, num){
//First, clean out all the garbage!
this.clean();

//Now, append new particles to the end
var n, limit = (num && typeof num === 'number') ? num : 1;
for (n = 0; n < limit; n++){
particles.push( new Particle(props) );
}
};

//A couple examples
particles.add({ //Add a single blueFlame
type: "blueFlame",
size: 10,
x: 200,
y: 200
});

particles.add({ //Add 4 redFlames
type: "redFlame",
size: 10,
x: 300,
y: 200
}, 4);

particles.add(function(){//Add 4 greenFlames, with randomized XY cooridinates
this.x = Math.round(Math.random() * 1000);
this.y = Math.round(Math.random() * 1000);
this.size = 20;
this.type = "greenFlame";
}, 4);

需要管理的代码更少。我不确定哪种方式更快,但我敢打赌速度差异可以忽略不计。当然,您可以通过快速创建jsPerf.来自行检查。

关于javascript - 如何在 JavaScript/jQuery 中为粒子系统重用数组中的对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23220403/

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