如何以恒定速度使鼠标单击方向移动?

Use*_*049 1 delphi

我试图使一个形状沿着鼠标点击的方向移动一定距离.我尝试为鼠标点击事件的x和y创建变量,并在x和y中创建到达鼠标点击位置的距离,并使用计时器划分+截断值以使形状在该方向上移动,虽然我的问题是我需要移动特定距离的形状,无论光标在哪里,只需使用鼠标单击方向,以及使用此方法形状不会以恒定速度移动.

当前代码:鼠标按下:

mx := x;
my := y;
Run Code Online (Sandbox Code Playgroud)

计时器:

shape1.left := shape1.Left + (mx - shape1.left + 8) div 32;
shape1.top := shape1.top + (my - shape1.top + 8) div 32;
Run Code Online (Sandbox Code Playgroud)

J..*_*... 5

您的方法的问题是您每单位时间移动的数量与形状和鼠标单击位置之间的距离成正比.从鼠标位置获得的所有方法都是一个方向,获得方向的标准方法是规范化感兴趣点之间形成的向量.

除以在感兴趣点之间形成的线段的大小,在您想要的方向上产生长度为1px的单位矢量.然后必须通过速度缩放以产生运动增量.

这与整数一样笨拙,因为你的增量必须在每一步舍入,但可以按如下方式完成:

procedure TForm1.Timer1Timer(Sender: TObject);
const
  SPEED = 5;
var
  dx, dy : integer;
  mag : double;
begin
  dx := mx - Shape1.Left;                           {vector x}
  dy := my - Shape1.Top;                            {vector y}
  mag := Sqrt(dx*dx + dy*dy);                       {vector magnitude}  
  if (Abs(dx) > SPEED) or (Abs(dy) > SPEED) then 
  begin
    { use Ceil to move at least 1px. }
    Shape1.Left := Shape1.Left 
                   + Sign(dx)*Ceil(SPEED*Abs(dx)/mag);  {divide by mag}
    Shape1.Top := Shape1.Top                            {to give a unit}
                   + Sign(dy)*Ceil(SPEED*Abs(dy)/mag);  {vector in the}   
  end else begin                                        {required direction}
    Shape1.Left := mx;        {snap to mx/my if close enough}
    Shape1.Top := my;         {deals with rounding issues...}  
  end;
end;
Run Code Online (Sandbox Code Playgroud)

否则,更优雅的是,您可以将形状的位置存储在浮点对中,并且仅在设置控件的位置时舍入为整数.这避免了整个过程中每个步骤的整数精度问题.