【问题标题】:ImpactJS - variable values valid until passed to class constructor then become NaNImpactJS - 变量值在传递给类构造函数之前有效,然后变为 NaN
【发布时间】:2013-05-24 22:12:36
【问题描述】:

抱歉,帖子太长了,但我想尽可能详细

所以我正在创建一个带有几个自定义 ig.Class 实例的插件。一个是 Vector 实现:Vec2 然后我有一个粒子类:

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();
    }
});

接下来我在另一个类中有这个轮胎功能:

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;
    }

最后这个更新函数与轮胎函数在同一个类中:

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]);
            }
        }
    }

我得到的错误是在更新函数中的这一行:var velocity = particles[i].pos.sub(particles[i].last).scale(this.friction); 特别是错误是说它不能调用未定义的方法sub。我将上面的轮胎方法更改为如下所示,以便可以对其进行调试:

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;
    }

当我记录pos 变量时,我得到正确的值输出到控制台,但是如果仍然得到错误。我唯一能想到的是,在pos 变量在tire 方法中创建与在Particle 构造函数中传递和分配变量之间的某个位置,它会丢失其值并导致粒子具有@987654333 @ NaN 的值,当我在错误行 (var velocity = particles[i].pos.sub(particles[i].last).scale(this.friction);) 上方记录 var particles 时可以看到。我真的不知道出了什么问题我试过改变Particle构造函数对参数pos的分配以多种方式分配它(通过Vec2.mutableSet()方法和直接设置。但无论我做什么它仍然结果在粒子的 NaN 值中。

谁能看到我不是的东西?谢谢

【问题讨论】:

  • 不要使用for ... in 进行数组迭代!始终使用数字索引变量。
  • 好的,我正在将 VerletJS 移植到 ImpactJS 插件中,所以这不是我的全部代码,只是出于好奇,你为什么不呢?
  • for ... in 构造不保证迭代顺序,它还会遍历数组对象的非数字索引属性。除非您真的知道自己需要这样做,否则这通常被认为是一种不好的做法。
  • 我认为你只需要添加一些console.log() 调用来跟踪你的粒子对象的更新。可能某些数学表达式被字符串或null 值污染。
  • 我在init() 函数中添加了console.log(pos) 作为第一行,该函数记录来自pos 参数的正确值,以及在我将pos 分配给this.pos 之后console.log(this.pos)然后值是 NaN 所以我如何分配导致问题的值?

标签: javascript parameter-passing nan impactjs


【解决方案1】:

想通了,正在加载一个覆盖Particle 类的javascript 文件。删除了带有 javascript 文件的脚本标签,一切都很好

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-05-15
    • 2020-01-16
    • 2021-12-25
    • 2016-05-23
    • 1970-01-01
    • 2013-08-10
    • 1970-01-01
    相关资源
    最近更新 更多