pixijs / particle-emitter

A particle system for PixiJS
http://pixijs.io/particle-emitter/docs
MIT License
799 stars 127 forks source link

wrong `acceleration speed` compute #102

Closed finscn closed 5 years ago

finscn commented 5 years ago

In current pixi-particles , the code about acceleration speed is like this:

this.velocity += this.acceleration * deltaTime;

this.position = this.velocity * deltaTime;

It's wrong.

The right way is :

var newVelocity = this.velocity +  this.acceleration * deltaTime;

this.position = ( newVelocity + this.velocity) / 2 * deltaTime;

this.velocity = newVelocity;

image

x is delta position (displacement), t is delta time. V0 is old velocity, Vt is new velocity.

andrewstart commented 5 years ago

While that is a more accurate way of calculating positional changes, it would complicate the code a little (and potentially slow it down by adding more if/elses) as we don't always have acceleration. I think that the current method is close enough, unless deltaTime is extremely large, which would be bad in its own right.

finscn commented 5 years ago

There is no more if/elses.

//handle movement
if(this._doNormalMovement)
{
    let deltaX;
    let deltaY;

    //interpolate speed
    if (this._doSpeed)
    {
        let speed = this.speedList.interpolate(lerp) * this.speedMultiplier;
        ParticleUtils.normalize(this.velocity);
        ParticleUtils.scaleBy(this.velocity, speed);

        deltaX = this.velocity.x * delta;
        deltaY = this.velocity.y * delta;
    }
    else if(this._doAcceleration)
    {
        const oldVX = this.velocity.x;
        const oldVY = this.velocity.y;

        this.velocity.x += this.acceleration.x * delta;
        this.velocity.y += this.acceleration.y * delta;

        if (this.maxSpeed)
        {
            let currentSpeed = ParticleUtils.length(this.velocity);
            //if we are going faster than we should, clamp at the max speed
            //DO NOT recalculate vector length
            if (currentSpeed > this.maxSpeed)
            {
                ParticleUtils.scaleBy(this.velocity, this.maxSpeed / currentSpeed);
            }
        }

        deltaX = (oldVX + this.velocity.x) / 2 * delta;
        deltaY = (oldVY + this.velocity.y) / 2 * delta;
    }
    else
    {
        deltaX = this.velocity.x * delta;
        deltaY = this.velocity.y * delta;
    }

    //adjust position based on velocity
    this.position.x += deltaX;
    this.position.y += deltaY;
}

It just does more + & / & = :

    deltaX = (oldVX + this.velocity.x) / 2 * delta;
    deltaY = (oldVY + this.velocity.y) / 2 * delta;
finscn commented 5 years ago

you said "unless deltaTime is extremely large" In fact , many game use 30fps , the timeStep(deltaTime) === 33ms. it's already so big for some fast particles.

andrewstart commented 5 years ago

Added in 4.1.0.