慢慢地将一个角度改变为另一个角度

时间:2014-01-05 00:34:01

标签: javascript math trigonometry

Skip to JSFiddle
我正在创建一个与鼠标交互的有趣脚本。我决定要一个物体慢慢地跟着鼠标。我做了这样的对象,它具有以下属性:

speed - current speed of the object
speed change ratio - derivative of the speed function: "How's the speed changing now?"
direction - radian angle upon which the object is moving
direction change - same as for speed, this is used to change the direction

随机生成更改比率并将其添加到speeddirection

//Do not do it allways
if(rand(0,5)>3) {
  speed+=speed_change;
  direction+=dir_change;
  //Only sometimes, so that they actually have some time to take effect
  if(rand(0,10)<=3) { 
    dir_change = rand(-1,1);
    speed_change = rand(-2,2)/10;
  }
}

只有这样才能使速度变化效果更加平滑,增加比率和比率比率等...我无法想象其他任何事情。

到现在为止。您已经看到默认情况下的移动是随机的,这是预期的。如果我将随机比率变为无效并应用此代码,则它会跟随鼠标位置:

  var my_angle = Math.atan2(flyPos[1]-flyTo[1], flyPos[0]-flyTo[0])-Math.PI;
  direction = my_angle;
  //Inital speed is random, so here is some fix for it (the class also has soft-cap for speed, so it won't reach high numbers)
  if(speed<0)
    speed_change = 0.1;

这是我所谈到的速度的简单软帽,以防你想看到它:

if(Math.abs(speed)>6) {
  //Dividing speed by |speed| leads +1 or -1, but it's pretty unefective
  speed_change = (-1)*(speed/Math.abs(speed));
} 

现在,我想要的是改变dir_change而不是direction,这样如果目标发生变化(这种情况一直发生在鼠标光标上),它就不会立即转动而是顺利转动(痘痘)有点像汽车会。)

我尝试了这个计算:

dir_change -= (direction-my_angle)/Math.PI;

/Math.PI旨在减少更改大小,-应该产生差异。不行。

I also made example on JSFiddle ,希望您不要仅仅因为不清楚而跳过这个问题。谢谢你的帮助。

This is what it can do though, it's quite fun :)

1 个答案:

答案 0 :(得分:1)

嗯,这是你的解决方案的工作小提琴-> Fiddle Link <-

请注意,我已经更改了一些变量名称,并添加了注释。

关于代码的一些问题:
负角度是因为您使用current-target而不是target-current来调用atan2。你应该给atan2一个flyTo和flyPos之间的区别,因为这相当于从你所在的位置查看目标(这就是atan2的工作方式)。所以:

var my_angle = Math.atan2(flyPos[1]-flyTo[1], 
                          flyPos[0]-flyTo[0]) -Math.PI;

应该是:

var my_angle = Math.atan2(flyTo[1]-flyPos[1], 
                          flyTo[0]-flyPos[0]);

然后你不应该担心-PI

速度应始终为正,因为它是标量,我们有方向(负速度=负方向的正速度)。

我添加了decelerateaccelerate方法,主要是为了避免文本试图到达目标时出现令人讨厌的“嗡嗡声”,并在小小的位置之间来回移动。现在它会在它越来越近时减速,如果你离开它会加速。

需要注意的一点:根据MDN,您应该像这样打电话给setInterval

setInterval(  letter.flyAway, refreshEvery );  

而不是使用自我执行的方法(并且它在眼睛上也更容易)。

为了获得良好的回合,我们要做的是查看当前方向,然后慢慢朝目标方向变化。 以下天真实现中存在一个可能的错误(其中dPhi代表delta phi,一个小角度):

 if ( Math.abs(angle_to_target - direction) > dPhi )
    if (angle_to_target > direction)
      direction += dPhi;
    else
      direction -= dPhi;
  else
    direction = angle_to_target;

如果方向是例如179度,目标是181度,而不是关闭2度间隙,它将经过另一侧的358度。原因是atan2处理角度的方式,返回-PIPI之间的值。解决方案是在几种情况下添加2*PI

if  (direction - Math.PI > angle_to_target ) 
    angle_to_target += 2*Math.PI; 
  if  (angle_to_target - Math.PI > direction ) 
    direction += 2*Math.PI;

你去,用start工作,stop按钮会显示结果。

您可能希望将随机speed / angle添加到该解决方案,但现在应该不难:)