美文网首页
到达行为

到达行为

作者: 大龙10 | 来源:发表于2022-06-29 11:15 被阅读0次

    书名:代码本色:用编程模拟自然系统
    作者:Daniel Shiffman
    译者:周晗彬
    ISBN:978-7-115-36947-5
    第6章目录

    6.4 到达行为

    1、改进

      上例中,在模拟小车寻找行为时,小车会超过目标位置,然后又回头继续寻找目标,最后往复运动。
      这是因为小车在寻找目标时过于兴奋,以至于它无法根据目标的距离确定合理的运动速度。无论目标是远是近,它始终以最大的速度运动。

      在某些场景中,这是我们想要的行为(比如,导弹在射击过程中,朝着目标运动的速度应当尽可能快)。
      但在另一些场景中(比如泊车,或者模拟蜜蜂停在花朵上),小车应该改变思维方式,在计算运动速度时应该考虑目标的距离。

    • 第1帧:我距离目标很远,我希望尽快地朝着目标运动!
    • 第2帧:我距离目标很远,我希望尽快地朝着目标运动!
    • 第3帧:我离目标还有些距离,我希望尽快地朝着目标运动!
    • 第4帧:我越来越接近目标了,我希望减慢速度!
    • 第5帧:我快要到达目标了,我希望慢慢地移向目标!
    • 第6帧:我已经到达目标了,我要停下来!

    2、如何实现

      如何用代码实现“到达”行为?回到seek()函数的实现,我们用一行代码设置了所需速度的大小。

    PVector desired = PVector.sub(target,location);
    desired.normalize();
    desired.mult(maxspeed);
    
    • 在示例代码6-1中,所需速度向量的大小总是等于“最大”速度。
      如果所需速度的大小等于距离的一半,会怎么样?
    PVector desired = PVector.sub(target,location);
    desired.div(2);
    
    • 上面的代码根据目标的距离确定所需速度,尽管这种做法准确地描述了我们的意图,但它并不能产生合理的模拟效果。试想,如果两者之间的距离是10像素,5像素/帧的所需速度就会显得过快。但如果让所需速度的大小等于距离的5%,我们就能得到合理的模拟效果。
    PVector desired = PVector.sub(target,location);
    desired.mult(0.05);
    

    3、更好的方法

    • Reynolds描述了一种更好的方法,假设目标附近有一个给定半径的圆圈,如果小车运动到圆圈之内,它就减速——如果小车位于圆圈的边缘,它的所需速度就等于最大速率;如果已经位于目标位置,所需速度就等于0。


      图6-10
    • 换句话说,如果小车和目标的距离小于半径r,我们就将两者的距离映射为所需速度,映射的目标范围是0至最大速率之间。

    4、转向力的本质

    • 到达行为的模拟展示了“所需速度-当前速度”公式的神奇之处。
    • 物体的转向行为则有所不同,物体有了转向力之后,它像是在说:“我可以感知环境。”
    • 转向力并非完全基于所需速度,而是同时基于所需速度和当前速度。只有那些有生命的物体才知道自己的当前速度。
    • 转向力在本质上是当前速度的误差体现:
      “我应该朝着这个方向运动,实际上却朝着另一个方向运动。误差就是两个方向之间的差异。”
      在误差的基础上施加一个转向力会创造更贴近现实的模拟效果。在引力作用下,无论物体和目标之间的距离有多近,它所受的力永远不会远离目标;但在转向力的到达行为中,如果它朝目标运动的速度过快,转向力会让你减速以纠正误差。

    5、示例

    示例代码6-2 到达转向行为

      // A method that calculates a steering force towards a target
      // STEER = DESIRED MINUS VELOCITY
      void arrive(PVector target) {
        PVector desired = PVector.sub(target,position);  // A vector pointing from the position to the target
        float d = desired.mag();
        // Scale with arbitrary damping within 100 pixels
        if (d < 100) {
          float m = map(d,0,100,0,maxspeed);
          desired.setMag(m);
        } else {
          desired.setMag(maxspeed);
        }
        // Steering = Desired minus Velocity
        PVector steer = PVector.sub(desired,velocity);
        steer.limit(maxforce);  // Limit to maximum steering force
        applyForce(steer);
      }
    

    6、结果

    相关文章

      网友评论

          本文标题:到达行为

          本文链接:https://www.haomeiwen.com/subject/zhawvrtx.html