C++ 使用具有设置延迟C+的鼠标事件平滑鼠标移动+;

C++ 使用具有设置延迟C+的鼠标事件平滑鼠标移动+;,c++,macros,mouseevent,mouse,smoothing,C++,Macros,Mouseevent,Mouse,Smoothing,我正在编写一个鼠标宏。它需要在每个点之间的设置延迟内满足屏幕上的某些点。例如,它必须在132ms内移动(x14,y30)。我遇到的问题是鼠标事件会跳到那个确切的位置,所以我需要包括一些平滑方法,以便它平滑地移动到每个点。(移动越平滑,宏效果越好)。目前我正在使用这种平滑每个动作的方法 这很好,但也有其局限性,例如,如果需要向左移动10个像素,并且平滑设置为20,它将继续跳跃 有人知道更精确的平滑鼠标移动的方法吗?(要求准确、流畅) void平滑(整数平滑、整数延迟、整数x、整数y){ 对于(in

我正在编写一个鼠标宏。它需要在每个点之间的设置延迟内满足屏幕上的某些点。例如,它必须在132ms内移动(x14,y30)。我遇到的问题是鼠标事件会跳到那个确切的位置,所以我需要包括一些平滑方法,以便它平滑地移动到每个点。(移动越平滑,宏效果越好)。目前我正在使用这种平滑每个动作的方法

这很好,但也有其局限性,例如,如果需要向左移动10个像素,并且平滑设置为20,它将继续跳跃

有人知道更精确的平滑鼠标移动的方法吗?(要求准确、流畅)

void平滑(整数平滑、整数延迟、整数x、整数y){
对于(int i=0;i<平滑;i++){
鼠标事件(1,x/平滑,y/平滑,0,0);
准确睡眠(延迟/平滑);
}
鼠标事件(1,x%平滑,y%平滑,0,0);
睡眠(延迟%平滑);
}

将点视为向量并在它们之间插值。 这通常被称为线性插值的“lerping”排序。 如果搜索线性插值,您可以找到许多可能有帮助的资源。 下面是一些可能有助于理解它是什么的信息

因为我手头有多余的时间,所以我打了一个程序的例子,这个程序也能做到这一点

#include <iostream>
#include <chrono>

struct Vec2d {
    double x;
    double y;
    Vec2d(double x, double y) : x(x), y(y) {};
};

Vec2d lerp(Vec2d const& a, Vec2d const& b, double t)  {
    double x((1.0 - t) * a.x + t * b.x);
    double y((1.0 - t) * a.y + t * b.y);
    return Vec2d(x, y);
}

int main(int argc, char* argv[]) {
    Vec2d p1(10, 10);
    Vec2d p2(20, 40);

    double maxTime(100); //max time 100 milliseconds
    double elapsedTime(0);
    std::chrono::time_point<std::chrono::system_clock> start(std::chrono::system_clock::now());
    std::chrono::time_point<std::chrono::system_clock> end(start);
    while(elapsedTime < maxTime) {
        elapsedTime += std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
        start = end;

        //This is where the lerping happens
        double t(elapsedTime / maxTime);
        Vec2d p3(lerp(p1, p2, t));

        //Show what's happening.
        std::cout << "p3: " << p3.x << ", " << p3.y << std::endl;
        end = std::chrono::system_clock::now();
    }

    return 0;
}
#包括
#包括
结构向量2D{
双x;
双y;
Vec2d(双x,双y):x(x),y(y){};
};
Vec2d lerp(Vec2d常量a、Vec2d常量b、双t){
双x((1.0-t)*a.x+t*b.x);
双y((1.0-t)*a.y+t*b.y);
返回向量2d(x,y);
}
int main(int argc,char*argv[]){
vec2dp1(10,10);
vec2dp2(20,40);
双最大时间(100);//最大时间100毫秒
双延时(0);
std::chrono::time_point start(std::chrono::system_clock::now());
std::chrono::时间点结束(开始);
while(elapsedTimestd::cout将点视为向量并在它们之间插值。
这通常被称为线性插值的“lerping”排序。
如果搜索线性插值,您可以找到许多可能有帮助的资源。
下面是一些可能有助于理解它是什么的信息

因为我手头有多余的时间,所以我打了一个程序的例子,这个程序也能做到这一点

#include <iostream>
#include <chrono>

struct Vec2d {
    double x;
    double y;
    Vec2d(double x, double y) : x(x), y(y) {};
};

Vec2d lerp(Vec2d const& a, Vec2d const& b, double t)  {
    double x((1.0 - t) * a.x + t * b.x);
    double y((1.0 - t) * a.y + t * b.y);
    return Vec2d(x, y);
}

int main(int argc, char* argv[]) {
    Vec2d p1(10, 10);
    Vec2d p2(20, 40);

    double maxTime(100); //max time 100 milliseconds
    double elapsedTime(0);
    std::chrono::time_point<std::chrono::system_clock> start(std::chrono::system_clock::now());
    std::chrono::time_point<std::chrono::system_clock> end(start);
    while(elapsedTime < maxTime) {
        elapsedTime += std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
        start = end;

        //This is where the lerping happens
        double t(elapsedTime / maxTime);
        Vec2d p3(lerp(p1, p2, t));

        //Show what's happening.
        std::cout << "p3: " << p3.x << ", " << p3.y << std::endl;
        end = std::chrono::system_clock::now();
    }

    return 0;
}
#包括
#包括
结构向量2D{
双x;
双y;
Vec2d(双x,双y):x(x),y(y){};
};
Vec2d lerp(Vec2d常量a、Vec2d常量b、双t){
双x((1.0-t)*a.x+t*b.x);
双y((1.0-t)*a.y+t*b.y);
返回向量2d(x,y);
}
int main(int argc,char*argv[]){
vec2dp1(10,10);
vec2dp2(20,40);
双最大时间(100);//最大时间100毫秒
双延时(0);
std::chrono::time_point start(std::chrono::system_clock::now());
std::chrono::时间点结束(开始);
while(elapsedTime
插值的一般公式为:

x=(1-t)·x0+t·x1

x…插值
x0…开始值
x1…目标值
t…插值参数在[0,1]范围内

当我意识到一些可能形成约束的事实时,我甚至打算写这篇文章作为答案(遗憾的是,OP没有明确提到)

  • 所有的运算都是关于整数值的。所以,做整数运算可能是首选
  • 使用增量值调用
    鼠标事件()
    以及
    AccurateSleep()
    。这可能由OP使用的API决定
  • 因此,我三思而后行,提出了以下类似于OPs的问题:

    #include <iostream>
    
    static int xMouse = 0, yMouse = 0, t = 0;
    
    void mouse_event(int _1, int dx, int dy, int _4, int _5)
    {
      xMouse += dx; yMouse += dy;
      std::cout << "mouse_event(" << _1 << ", " << dx << ", " << dy << ", " << _4 << ", " << _5 << "): "
        << xMouse << ", " << yMouse << '\n';
    }
    
    void AccurateSleep(int delay)
    {
      t += delay;
      std::cout << "AccurateSleep(" << delay << "): " << t << '\n';
    
    }
    
    void Sleep(int delay)
    {
      t += delay;
      std::cout << "Sleep(" << delay << "): " << t << '\n';
    }
    
    void Smoothing(int smoothing, int delay, int x, int y)
    {
        for (int i = 0; i < smoothing; i++) {
            mouse_event(1, x / smoothing, y / smoothing, 0, 0);
            AccurateSleep(delay / smoothing);
        }
        mouse_event(1, x % smoothing, y % smoothing, 0, 0);
        Sleep(delay % smoothing);
    }
    
    #define PRINT_AND_DO(...) std::cout << #__VA_ARGS__ << ";\n"; __VA_ARGS__ 
    
    int main()
    {
      PRINT_AND_DO(xMouse = 0; yMouse = 0; t = 0);
      PRINT_AND_DO(Smoothing(10, 132, 14, 30));
      PRINT_AND_DO(xMouse = 0; yMouse = 0; t = 0);
      PRINT_AND_DO(Smoothing(20, 15, 10, 0));
    }
    
    然后我修改了
    平滑()
    实现上述插值公式,并根据具体情况进行了一些调整:

  • 对于t,使用
    i/平滑
    (在[1,平滑]范围内使用
    i
  • 当循环对每个
    i
    进行插值时,保留上一次迭代的值,并用于计算
    mouse\u event()
    AccurateSleep()函数调用的增量值
  • 当然,运算顺序很重要,因为这是整数运算。因此,
    xI=i*x/平滑
    并不等同于
    xI=i/smoothing*x
    (即,这些积分运算不提供交换性)
  • 修改后的
    平滑()

    void平滑(整数平滑、整数延迟、整数x、整数y)
    {
    int x=0,y=0,t=0;
    for(inti=1;i是我阅读问题时的第一个想法(以及中提到的)

    插值的一般公式为:

    x=(1-t)·x0+t·x1

    x…插值
    x0…开始值
    x1…目标值
    t…插值参数在[0,1]范围内

    当我意识到一些可能形成约束的事实时,我甚至打算写这篇文章作为答案(遗憾的是,OP没有明确提到)

  • 所有的运算都是关于整数值的。所以,做整数运算可能是首选
  • 使用增量值调用
    鼠标事件()
    以及
    AccurateSleep()
    。这可能由OP使用的API决定
  • 因此,我再三考虑,并提出了以下类似于OPs的问题