0

I am currently making a macro that must be human-like. My basic req is that I give an array of x,y points into a for loop and it moves to each point. To make this movement smooth I am using a smoothing method that can be found in the forum/thread here: Smooth Mouse Movement using mouse_event with set delay C++ This smoothing method made by Scheff works extremely well and it is what I am using. I have just been trying to include some acceleration into it so that once it leaves its original point it speeds up then slows down when it reaches the next point. (I think I explained that pretty bad sorry)

This is the original code (from Scheff)

void Smoothing(int smoothing, int delay, int x, int y)
{
  int x_ = 0, y_ = 0, t_ = 0;
  for (int i = 1; i <= smoothing; ++i) {
    // i / smoothing provides the interpolation paramter in [0, 1]
    int xI = i * x / smoothing;
    int yI = i * y / smoothing;
    int tI = i * delay / smoothing;
    mouse_event(1, xI - x_, yI - y_, 0, 0);
    AccurateSleep(tI - t_);
    x_ = xI; y_ = yI; t_ = tI;
  }
}

This is my attempt to include a controllable acceleration into it

int total = 0;
void smoothing(int delay, int x, int y, int acceration)
{
    int x_ = 0, y_ = 0, t_ = 0;
    for (int i = 1; i <= delay - total; ++i) {
        // i / smoothing provides the interpolation paramter in [0, 1]
        int xI = i * x / delay;
        int yI = i * y / delay;
        int tI = i * (delay / delay) + total;
        mouse_event(1, xI - x_, yI - y_, 0, 0);
        //std::cout << "X: " << xI - x_ << " Y: " << yI - y_ << " Delay: " << tI - t_ << std::endl; //Management
        AccurateSleep(tI - t_);
        x_ = xI; y_ = yI; t_ = tI;

        total++;
    }
}

I know its a pitiful attempt but its the only way I could really think of. I wasn't sure whether to add some sort of acceleration to the x and y movements of whether to do the delay. (now that I think back to it, it has to be the x and y that gets acceleration) edit. Basically I don't know.

Sorry for the poor explanation and examples.

1 Answers1

2

Let's assume that we want to travel a distance of d with our mouse, using an initial acceleration a followed by deceleration of the same magnitude. Similar to the following movement profile over time:

Motion Profile

In this example, d=30 and a=5. The two motion parts (acceleration and deceleration) are separated by the d/2 line. You can define them by:

s(t) = {  a/2 * t^2                                     if t < tm
         -a/2 * (t - tm)^2 + a * tm * (t - tm) + d/2    otherwise 

The time tm is the point in time when you reach the middle point. It is

tm = sqrt(d / a)

And that's all you need. The adapted code could look as follows:

void Smoothing(int steps, int dx, int dy, int startX, int startY, double acceleration)
{
  double distance = std::sqrt(dx * dx + dy * dy);
  double tm = std::sqrt(distance / acceleration);
  for (int i = 1; i <= steps; ++i) {
    AccurateSleep(2.0 * tm / steps);
    double t = i * 2 * tm / steps;
    double s;
    if(t <= tm) {         
      s = 0.5 * acceleration * t * t;
    } else {
      s = -0.5 * acceleration * (t - tm) * (t - tm) + a * tm * (t - tm) + 0.5 * distance;
    }
    int xI = (int)std::round(startX + s * dx / distance);
    int yI = (int)std::round(startY + s * dy / distance);

    mouse_event(MOUSEEVENTF_ABSOLUTE, xI, yI, 0, 0); 
  }
}
Nico Schertler
  • 32,049
  • 4
  • 39
  • 70