有没有更好的方法来完成这个PIXI绳子鼠标追随者?

时间:2014-12-12 18:49:30

标签: javascript pixi.js

我使用PIXI.js创建了一个简单的鼠标跟随器。它根据鼠标移动创建均匀间隔的点,并沿这些点渲染纹理化的PIXI.Rope对象。 PIXI似乎很难渲染绳索,我想知道是否有更好的方法来实现这一点,或者我是否滥用绳索对象。

正如您在下面的示例中所看到的,这在大多数情况下都有效,但是快速移动鼠标或将绳索移到自身顶部会导致毛刺和伪影,这可能与PIXI的方式有关呈现渐变(以及我对它的误解)。

请参阅: http://plnkr.co/edit/6dB6QcKvSFlcT4k3OrMH?p=preview

(function()
{
  document.addEventListener('DOMContentLoaded', function()
  {
    PIXI.Point = window.Vector;

    var stage = new PIXI.Stage(0xFFFFFF);
    var renderer = PIXI.autoDetectRenderer(500, 500);

    document.body.appendChild(renderer.view);

    var resizeWindow = function()
    {
      w = window.innerWidth;
      h = window.innerHeight;
      renderer.resize(w,h);
      renderer.view.height = h;
      renderer.view.width = w;
    }
    resizeWindow()
    window.addEventListener('resize', resizeWindow)

    var tRope, rope, skeleton;
    var isDrawing = true, points = [], pointsSkeleton = [], threshold_lower = 10, threshold_upper = 15, lineLength = 1000;
    var animate;

    tRope = PIXI.Texture.fromImage("http://new.wethecollective.com/junk/rope2.png");
    tRope.height = 22;
    tRope.width = 1000;
    tBone = PIXI.Texture.fromImage("http://new.wethecollective.com/junk/bone.png");
    tBone.height = 10;
    tBone.width = 10;

    var addPoint = function(point, addToSkeleton)
    {
      if(addToSkeleton !== false)
      {
        addToSkeleton = true
      }

      points.push(point);

      if(addToSkeleton)
      {
        var bone = new PIXI.Sprite(tBone);
        bone.x = point.x - 5;
        bone.y = point.y - 5;
        pointsSkeleton[points.length -1] = skeleton.addChild(bone);
      }
    }
    var removePoint = function(index)
    {
      points.splice(index, 1);

      skeleton.removeChild(pointsSkeleton[index]);
      pointsSkeleton.splice(index, 1);
    }

    animate = function()
    {
      requestAnimationFrame(animate);
      // render the stage   
      renderer.render(stage);
    }

    var rlength = 0
    while(rlength < lineLength)
    {
      rlength += threshold_upper;
      addPoint(new PIXI.Point(rlength, 100), false);
    }

    rope = new PIXI.Rope(tRope, points);
    skeleton = new PIXI.DisplayObjectContainer();

    stage.addChild(rope);
    stage.addChild(skeleton);

    document.body.addEventListener('mousemove', function(e)
    {
      var pos = new PIXI.Point(e.clientX, e.clientY);
      var v = pos.clone().sub(points[points.length - 1]);
      l = v.length()
      if(l > threshold_lower)
      {
        if(l <= threshold_upper)
        {
          addPoint(pos);
        } else
        {
          var segment_l = 0;
          var divisions = Math.floor(l / threshold_upper)
          var divisionlength = l / divisions;
          var lastPos = points[points.length - 1];
          for(var i = 0; i < divisions; i++)
          {
            var v1 = v.clone();
            v1.setLength(divisionlength);
            v1.add(lastPos);
            addPoint(v1);
            segment_l += v1.length();
            lastPos = v1;
          }
        }
      }

      totalLength = 0;
      for(var i =0; i < points.length; i++)
      {
        if(i>0)
        {
          totalLength += points[i-1].clone().sub(points[i]).length()
        }
      }

      if(totalLength > lineLength)
      {
        var pointsnum = points.length;
        for(var i=0; i < pointsnum; i++)
        {
          var p = points[i].clone();
          totalLength -= p.sub(points[i+1]).length()
          removePoint(i);
          i--;
          pointsnum--;
          if(totalLength <= lineLength)
          {
            break;
          }
        }
      }
    });

    animate();
  });
})();

(function(NS)
{
  /*
  * @class Vector
  * @constructor 
  * @param x {Number} position of the point
  * @param y {Number} position of the point
  */
  NS.Vector = function(x, y)
  {
      /**
       * @property x 
       * @type Number
       * @default 0
       */
      this.x = x || 0;

      /**
       * @property y
       * @type Number
       * @default 0
       */
      this.y = y || 0;
  };

  /**
   * Creates a clone of this point
   *
   * @method clone
   * @return {Vector} a copy of the point
   */
  NS.Vector.prototype.clone = function()
  {
      return new NS.Vector(this.x, this.y);
  };

  NS.Vector.prototype.add = function(v) {
      this.x += v.x;
      this.y += v.y;
      return this;
  };

  NS.Vector.prototype.sub = function(v) {
      this.x -= v.x;
      this.y -= v.y;
      return this;
  };

  NS.Vector.prototype.invert = function(v) {
      this.x *= -1;
      this.y *= -1;
      return this;
  };

  NS.Vector.prototype.multiplyScalar = function(s) {
      this.x *= s;
      this.y *= s;
      return this;
  };

  NS.Vector.prototype.divideScalar = function(s) {
      if(s === 0) {
          this.x = 0;
          this.y = 0;
      } else {
          var invScalar = 1 / s;
          this.x *= invScalar;
          this.y *= invScalar;
      }
      return this;
  };

  NS.Vector.prototype.dot = function(v) {
      return this.x * v.x + this.y * v.y;
  };

  NS.Vector.prototype.length = function(v) {
      return Math.sqrt(this.x * this.x + this.y * this.y);
  };

  NS.Vector.prototype.lengthSq = function() {
      return this.x * this.x + this.y * this.y;
  };

  NS.Vector.prototype.normalize = function() {
      return this.divideScalar(this.length());
  };

  NS.Vector.prototype.distanceTo = function(v) {
      return Math.sqrt(this.distanceToSq(v));
  };

  NS.Vector.prototype.distanceToSq = function(v) {
      var dx = this.x - v.x, dy = this.y - v.y;
      return dx * dx + dy * dy;
  };

  NS.Vector.prototype.set = function(x, y) {
      this.x = x;
      this.y = y;
      return this;
  };

  NS.Vector.prototype.setX = function(x) {
      this.x = x;
      return this;
  };

  NS.Vector.prototype.setY = function(y) {
      this.y = y;
      return this;
  };

  NS.Vector.prototype.setLength = function(l) {
      var oldLength = this.length();
      if(oldLength !== 0 && l !== oldLength) {
          this.multiplyScalar(l / oldLength);
      }
      return this;
  };

  NS.Vector.prototype.invert = function(v) {
      this.x *= -1;
      this.y *= -1;
      return this;
  };

  NS.Vector.prototype.lerp = function(v, alpha) {
      this.x += (v.x - this.x) * alpha;
      this.y += (v.y - this.y) * alpha;
      return this;
  };

  NS.Vector.prototype.rad = function() {
      return Math.atan2(this.x, this.y);
  };

  NS.Vector.prototype.deg = function() {
      return this.rad() * 180 / Math.PI;
  };

  NS.Vector.prototype.equals = function(v) {
      return this.x === v.x && this.y === v.y;
  };

  NS.Vector.prototype.rotate = function(theta) {
      var xtemp = this.x;
      this.x = this.x * Math.cos(theta) - this.y * Math.sin(theta);
      this.y = xtemp * Math.sin(theta) + this.y * Math.cos(theta);
      return this;
  };

  // constructor
  NS.Vector.prototype.constructor = NS.Vector;


})(window)

请原谅我的意大利面条代码。我现在正在构建这个作为概念证明。

1 个答案:

答案 0 :(得分:0)

我通过从舞台上物理地移除绳索并在每个渲染通道上重新初始化来修复此问题。对我来说这感觉有些笨拙,但确实有效。

animate = function()
{
  requestAnimationFrame(animate);

  stage.removeChild(rope);
  rope = new PIXI.Rope(tRope, points);
  stage.addChildAt(rope,0);

  // render the stage   
  renderer.render(stage);
}