努力在 p5 js 中创建一条 smooth-moving 蛇 - 尾巴赶上头

struggling to create a smooth-moving snake in p5 js - tail catching up to head

我正在制作一个 p5 草图,上面有在屏幕上随机移动的小蛇。

不幸的是,每次急转弯时,尾巴都会追上头部。

这是我用来计算移动的函数,我尝试了几种不同的方法来计算速度,固定数字,相对于蛇的长度。

它应该通过在 semi-random 方向移动蛇头(点 [3])然后让每个 body 点向它前面的点移动相同的量来工作。这行不通,我觉得我的算法本身有问题。我对这些中间类型不熟悉random-walks,所以我大部分时间都是靠猜测。

this["moveCurve"] = function() {
    let newDir = this["oldDir"] + (random() - 1/2)*PI/6; 
    let velocity =  createVector(1,0); 
    velocity.setMag(5); 
    velocity.setHeading(newDir); 
    this["points"][3].add(velocity); 
    for (let i = 2; i >= 0; i--) { 
        this["points"][i].add(p5.Vector.sub(this["points"][i + 1],this["points"][i]).setMag(5)); 
    } 
    this["oldDir"] = newDir; 
}

如果您知道我可以做些什么来使这项工作正常进行,我很想听听您的建议。谢谢!

这看起来像是一个算法问题/而不是你如何实现它的错误。

下面是我解释为什么在这个算法中两点之间的差距必须减小的原因:

让我们只考虑一条两点蛇,在初始位置 Hi:(20, 0) 和 Ti:(0, 0) 处有两个点 Hi(头)和 Ti(尾)。所以,这里的航向是0弧度。

调用 moveCurve 时会发生什么?选择一个新的航向(让我们使用 PI/2,一个直角以便于想象)并使用固定速度 5 我们计算头部的新位置 (20, 5),我们称之为 Hf . T 也移动,但它也以相同的 5 个单位速度向 Hf 移动,最终大约为 (4.85, 1.21)。这两个最终位置之间的距离现在是 15.62657,比初始距离小。

为了形象化这一点,想想 Ti、Hi 和 Hf 之间形成的三角形。 Ti 和 Hi 构成了这个三角形的底边。 Ti 将沿着斜边移动到 Tf,而 Hi 将沿着另一侧移动。它们移动的方向形成一个小于 PI 弧度的角度,并且两个点都以相同的速度移动,因此直觉上这些点必须靠得更近。

那么如何解决呢?好吧,如果我们考虑我们的小蛇的运动,尾巴朝一个不错的方向移动但太远了。一种解决方案可能是缩放速度矢量以保持点之间的固定距离而不是使用固定速度。例如,您可以沿斜边从 Hf 向 Ti 步进 20 个单位,而不是示例中从 Ti 向 Hf 沿斜边步进 5 个单位。我不确定这对你的蛇有何影响,只是一个想法!

继续滑行!

幸运的是,事实证明 p5 的文档本身为我提供了答案。通过调整 here 中的代码以使用 p5 Vectors,我能够使其全部正常工作。

segLengths属性是在制作对象时定义的,只是取所有点之间的距离。

this["moveCurve"] = function() {
    let newDir = this["oldDir"] + (random() - 1/2)*PI/6;
    let velocity = p5.Vector.fromAngle(newDir).setMag(5);
    this["points"][3].add(velocity);
    for (let i = 2; i >= 0; i--) {
      this["points"][i].set(p5.Vector.sub(this["points"][i+1], p5.Vector.fromAngle(p5.Vector.sub(this["points"][i+1],this["points"][i]).heading()).setMag(this["segLengths"][i])));
    }
    this["oldDir"] = newDir;
  }

我可能会花一点时间尝试稍微清理一下代码,目前对我来说有点乱。但它有效。