【问题标题】:C# smooth object movementC# 平滑对象移动
【发布时间】:2011-04-30 06:03:17
【问题描述】:

我拥有通过 C# 代码移动和单击鼠标所需的所有代码,但我不想将鼠标位置设置为 X 和 Y;那会看起来很生涩。相反,我希望在 Z 秒内从点 X1, Y1 平滑过渡到点 X2, Y2。类似于关键帧。

我正在寻找类似这样的方法:

public void TransitionMouse(int x, int y, double durationInSecs)

它只会在durationInSecs 秒内将鼠标从当前位置平滑地移动到x 和y。我有一个函数叫做:

public void MoveMouse(int x, int y)

立即将鼠标移至x、y。


编辑

感谢大家的帮助!这是完成并经过测试的代码:

    [DllImport("user32.dll")]
    static extern bool SetCursorPos(int X, int Y);

    public void TransitionMouseTo(double x, double y, double durationSecs)
    {
        double frames = durationSecs*100;

        PointF vector = new PointF();
        PointF mousePos = Cursor.Position;

        vector.X = (float)((x - mousePos.X) / frames);
        vector.Y = (float)((y - mousePos.Y) / frames);

        for (int i = 0; i < frames; i++)
        {
            SetCursorPos((int)(mousePos.X += vector.X), (int)(mousePos.Y += vector.Y));
            Thread.Sleep((int)((durationSecs / frames) * 1000.0));
        }
    }

【问题讨论】:

    标签: c# transition smooth keyframe


    【解决方案1】:

    实际上取决于您对平滑的定义,但是大多数“平滑”运动算法使用样条在 2 个或更多数据点之间进行插值。

    这可能会有所帮助 http://geekswithblogs.net/JuanDoNeblo/archive/2007/10/25/Data-Interpolation-with-SPLINE-in-Csharp.aspx

    【讨论】:

      【解决方案2】:

      您可以通过多种方式做到这一点。一种选择是计算每帧移动鼠标所需的向量,并将其在一段时间内应用于鼠标位置。

      因此,如果我们在位置 5,5 并且想要在 10 帧内移动到 20,30,我们的向量将如下所示:

      val = (target - start) / frames;

      x = (20 - 5) / 10; y = (30 - 5) / 10;

      向量 = 1.5,2.5

      然后,在您的 TransitionMouse 方法中,您可以使用 Thread.Sleep 方法控制速度,在您希望的任何持续时间内缓慢地将矢量应用到鼠标位置。代码可能如下所示:

      public void TransitionMouseTo(int x, int y, int durationSecs)
      {
          int frames = 10;
      
          PointF vector = new PointF();
      
          vector.X = (x - Cursor.Position.X) / frames;
          vector.Y = (y - Cursor.Position.Y) / frames;  
      
          for (int i = 0; i < frames; i++)
          {
              Point pos = Cursor.Position;
      
              pos.X += vector.X;
              pos.Y += vector.Y;
      
              Cursor.Position = pos;
      
              Thread.Sleep((durationSecs / frames) * 1000);
          }
      }
      

      另一种方法是使用Bresenhams algorithm 计算鼠标光标将通过的所有点,然后循环遍历每个点并使用 Thread.Sleep 再次将其应用于光标以保持时间正确。

      史蒂夫

      【讨论】:

      • -1 对我来说很苛刻,但是 "Cursor.Position.X += vector.X" 和 "Cursor.Position.Y += vector.Y" 不起作用。
      • 我可以补充一点,你不能设置 Cursor.Position,你必须使用 Win32 函数 SetCursorPos。但是改了之后就可以了! :D
      • 好吧,我以为你可以,但你明白了 :)。我必须承认我在发布之前没有测试代码。
      • @TheAdamGaskins,你能发布你的TransitionMouseTo函数的工作代码吗?
      • @TheAdamGaskins,感谢您的代码。我认为您可以只使用 Cursor.Position=new Point((int)(mousePos.X += vector.X), (int)(mousePos.Y += vector.Y)) 来替换 SetCursorPos 线。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-08-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多