0

Sorry for the long post, but i wanted to be as detailed as possible

So i'm creating a plugin with a couple custom ig.Class instances. one is a Vector implementation: Vec2 then i have a particle class:

Particle = ig.Class.extend({
    pos: null,
    last: null,
    init: function (pos) {
        this.pos = new Vec2().mutableSet(pos.x, pos.y);
        this.last = this.pos;
    },
    draw: function (ctx) {
        ctx.beginPath();
        ctx.arc(this.pos.x, this.pos.y, 2, 0, 2 * Math.PI);
        ctx.fillStyle = "#2dad8f";
        ctx.fill();
    }
});

next i have this tire function inside another class:

tire: function (origin, radius, segments, spokeStiffness, treadStiffness) {
        var stride = (2 * Math.PI) / segments;

        var composite = new Composite();

        // particles
        for (var i = 0; i < segments; i++) {
            var theta = i * stride;
            composite.particles.push(new Particle(new Vec2(origin.x + Math.cos(theta) * radius, origin.y + Math.sin(theta) * radius)));
        }
        var center = new Particle(origin);
        composite.particles.push(center);
        // constraints
        for (i = 0; i < segments; i++) {
            composite.constraints.push(new DistanceConstraint(composite.particles[i], composite.particles[(i + 1) % segments], treadStiffness));
            composite.constraints.push(new DistanceConstraint(composite.particles[i], center, spokeStiffness))
            composite.constraints.push(new DistanceConstraint(composite.particles[i], composite.particles[(i + 5) % segments], treadStiffness));
        }

        this.composites.push(composite);
        return composite;
    }

and finally this update function inside the same class as the tire function:

update: function (step) {
        for (var c in this.composites) {
            for (var i in this.composites[c].particles) {
                var particles = this.composites[c].particles;
                // calculate velocity
                var velocity = particles[i].pos.sub(particles[i].last).scale(this.friction);

                // ground friction
                if (particles[i].pos.y >= this.height - 1 && velocity.length2() > 0.000001) {
                    var m = velocity.length();
                    velocity.x /= m;
                    velocity.y /= m;
                    velocity.mutableScale(m * this.groundFriction);
                }

                // save last good state
                particles[i].last.mutableSet(particles[i].pos);

                // gravity
                particles[i].pos.mutableAdd(this.gravity);

                // inertia  
                particles[i].pos.mutableAdd(velocity);
            }
        }
        // relax
        var stepCoef = 1 / step;
        for (var c in this.composites) {
            var constraints = this.composites[c].constraints;
            for (var i = 0; i < step; ++i) {
                for (var j in constraints) {
                    constraints[j].relax(stepCoef);
                }
            }
        }

        // bounds checking
        for (var c in this.composites) {
            var particles = this.composites[c].particles;
            for (var i in particles) {
                this.bounds(particles[i]);
            }
        }
    }

the error i am getting is at this line in the update function: var velocity = particles[i].pos.sub(particles[i].last).scale(this.friction); specifically the error is saying that it cannot call method sub of undefined. i changed the tire method above to look like this so i could debug it:

tire: function (origin, radius, segments, spokeStiffness, treadStiffness) {
        var stride = (2 * Math.PI) / segments;

        var composite = new Composite();

        // particles
        for (var i = 0; i < segments; i++) {
            var theta = i * stride;
            var x = origin.x + Math.cos(theta) * radius;
            var y = origin.y + Math.sin(theta) * radius;
            var pos = new Vec2(x, y);
            console.log(pos);
            var particle = new Particle(pos);
            composite.particles.push(particle);
        }
        var center = new Particle(origin);
        composite.particles.push(center);
        // constraints
        for (i = 0; i < segments; i++) {
            composite.constraints.push(new DistanceConstraint(composite.particles[i], composite.particles[(i + 1) % segments], treadStiffness));
            composite.constraints.push(new DistanceConstraint(composite.particles[i], center, spokeStiffness))
            composite.constraints.push(new DistanceConstraint(composite.particles[i], composite.particles[(i + 5) % segments], treadStiffness));
        }

        this.composites.push(composite);
        return composite;
    }

when i log the pos variable i get the proper values being output to the console, however if still get the error. the only thing i can think is that somewhere between where the pos variable is created in the tire method and when it is passed and assigned in the Particle constructor it losses its value and results in the particle having a pos.x / pos.y value of NaN which i can see when i log the var particles above the error line (var velocity = particles[i].pos.sub(particles[i].last).scale(this.friction);). I really have no idea whats going wrong i've tried changing the Particle constructor's assignment of the parameter pos to assign it multiple ways (through the Vec2.mutableSet() method and setting directly. but no matter what I do it still results in a NaN value for the particle.

Can anyone see something that i am not? thanks

Joe
  • 1,326
  • 7
  • 34
  • 52
  • Don't use `for ... in` for array iteration! Always use a numeric index variable. – Pointy May 29 '13 at 15:10
  • okay, i'm porting VerletJS to an ImpactJS plugin so it's not all my code, just out of curiosity why shouldn't you? – Joe May 29 '13 at 15:12
  • The `for ... in` construct doesn't guarantee iteration order, and it'll also iterate through non-numerically-indexed properties of the array object. It's just generally considered a bad practice unless you really know that you need to do it that way. – Pointy May 29 '13 at 15:14
  • I think you just need to add some `console.log()` calls to track the updates to your Particle objects. Probably some math expressions are being contaminated with strings or `null` values. – Pointy May 29 '13 at 15:16
  • i added a `console.log(pos)` as the first line in the `init()` function which logs the proper values from the `pos` parameter, and `console.log(this.pos)` after i assign `pos` to `this.pos` and then the values are NaN so its how i'm assigning the values that's causing the problem? – Joe May 29 '13 at 17:04
  • i tried every which way i can think of to assign the values, i changed the default values of `pos` and `last` to `new Vec2()` and that didn't affect it either – Joe May 29 '13 at 17:11

1 Answers1

1

figured it out, there was a javascript file being loaded that was overriding the Particle class. removed the script tag with the javascript file and all is well

Joe
  • 1,326
  • 7
  • 34
  • 52