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
随机生成更改比率并将其添加到speed
和direction
:
//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 ,希望您不要仅仅因为不清楚而跳过这个问题。谢谢你的帮助。
答案 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
。
速度应始终为正,因为它是标量,我们有方向(负速度=负方向的正速度)。
我添加了decelerate
和accelerate
方法,主要是为了避免文本试图到达目标时出现令人讨厌的“嗡嗡声”,并在小小的位置之间来回移动。现在它会在它越来越近时减速,如果你离开它会加速。
需要注意的一点:根据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
处理角度的方式,返回-PI
和PI
之间的值。解决方案是在几种情况下添加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
添加到该解决方案,但现在应该不难:)