I am making a game in HTML5, and now I just got a disturbing problem.
In my game I have an Array with all the particles, all the particles have expire-timers, with different random generated delays.
When the expire-timers expire they delete there own Object with the Array.splice() function, that causes trouble, since the Array.splice() function will mess up the order of the Array.
First I had the function like this: (n = Blood particles to spawn, and x and y = starting point.) (All particles is spread random directions from the middle, and then they are decelerated by friction)
function spawnBlood(x, y, n) {
for (var i = 0; i < n; i++) {
var tetra = Math.floor(Math.random() * 360) * (180 / Math.PI)
var speed = Math.floor(Math.random() * 4) + 3
var j = particles.length
particles.push({
x: x,
y: y,
vx: Math.cos(tetra) * speed,
vy: Math.sin(tetra) * speed,
r: 1.5,
angle: 0,
expireTimer: setTimeout(function(j) {
return function() {
particles.splice(j, 1)
}
}(j), Math.floor(Math.random() * 500) + 500),
})
}
}
Then I had the function like this and did not have the splice function anymore so that won't make trouble with the Arrays order, but still one problem, when looping through the array to change x and y values for example to apply friction it fails. The fail is caused by that it can't define values from null:
function spawnBlood(x, y, n) {
for (var i = 0; i < n; i++) {
var tetra = Math.floor(Math.random() * 360) * (180 / Math.PI)
var speed = Math.floor(Math.random() * 4) + 3
particles.push({
x: x,
y: y,
vx: Math.cos(tetra) * speed,
vy: Math.sin(tetra) * speed,
r: 1.5,
angle: 0,
expireTimer: setTimeout(function(i) {
return function() {
particles[i] = null
for (var j = 0; j < particles.length; j++) {
if (particles[particles.length - 1] == null) {
particles.splice(particles.length - 1, 1)
}
}
}
}(i), Math.floor(Math.random() * 500) + 500),
})
}
}
I had a similar problem when making expire-timers for my own audio function in the game but tricked the Errors by replacing null with new Audio(""). Since this is related to objects that doesn't work, so I wonder if there might be a similar way to make fake Objects that do not return Errors if they don't have the specified value. An example:
For Objects in this case this will throw an Error:
null.x *= friction <---- friction = 0.8 though, will throw an Error
But it works with the fake new Audio when its about audio:
new Audio().play() <---- Won't throw an Error
Is there any way to make a fake Object that doesn't return error if it doesn't have the specified value as in the example x? Or is this the wrong way, is there maybe another solution that won't mess up the Array and the Objects?
Thanks.
function spawnBlood(x, y, n) {
for (var i = 0; i < n; i++) {
var tetra = Math.floor(Math.random() * 360) * (180 / Math.PI)
var speed = Math.floor(Math.random() * 4) + 3
particles.push(new function() {
this.x = x
this.y = y
this.vx = Math.cos(tetra) * speed
this.vy = Math.sin(tetra) * speed
this.r = 1.5
this.angle = 0
this.expireTimer = setTimeout(function(self) {
return function() {
particles.splice(particles.indexOf(self), 1)
}
}(this), Math.floor(Math.random() * 500) + 500)
})
}
}
Ok FINALLY!
@tewathia - Is this a good solution or can it be improved, I mean like isn't there any other way than using "new function()" to make an object that can retrieve it's own "this"?
Have you tried keeping a dummy object (with all properties set to 0) in place of the particle element that you want to delete? Replace
particles[i] = null
withAnother solution might be keeping the
particles[i] = null
line, but modifying the code, where you apply the friction to thex
andy
, to check whether the object in question has those properties or not.