Array with multiple Objects with expire-timers fai

2019-04-02 05:12发布

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"?

1条回答
We Are One
2楼-- · 2019-04-02 05:24

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 with

particles[i] = {
    x: 0,
    y: 0,
    vx: 0,
    vy: 0,
    r: 0,
    angle: 0
};

Another solution might be keeping the particles[i] = null line, but modifying the code, where you apply the friction to the x and y, to check whether the object in question has those properties or not.

if(particles[i].hasOwnProperty('x') && particles[i].hasOwnProperty('y')){
//apply friction
}
查看更多
登录 后发表回答