C# moviendo el mouse de manera realista

C# moviendo el mouse de manera realista

Probé el método de cálculo del arco, resultó demasiado complejo y, al final, no parecía realista. Las líneas rectas parecen mucho más humanas, como sugiere JP en su comentario.

Esta es una función que escribí para calcular un movimiento lineal del mouse. Debería ser bastante autoexplicativo. GetCursorPosition() y SetCursorPosition(Point) son contenedores de las funciones de win32 GetCursorPos y SetCursorPos.

En cuanto a las matemáticas, técnicamente, esto se llama interpolación lineal de un segmento de línea.

public void LinearSmoothMove(Point newPosition, int steps) {
    Point start = GetCursorPosition();
    PointF iterPoint = start;

    // Find the slope of the line segment defined by start and newPosition
    PointF slope = new PointF(newPosition.X - start.X, newPosition.Y - start.Y);

    // Divide by the number of steps
    slope.X = slope.X / steps;
    slope.Y = slope.Y / steps;

    // Move the mouse to each iterative point.
    for (int i = 0; i < steps; i++)
    {
        iterPoint = new PointF(iterPoint.X + slope.X, iterPoint.Y + slope.Y);
        SetCursorPosition(Point.Round(iterPoint));
        Thread.Sleep(MouseEventDelayMS);
    }

    // Move the mouse to the final destination.
    SetCursorPosition(newPosition);
}

Convertí el WindMouse función mencionada anteriormente en C# y en realidad es bastante realista. Tenga en cuenta que esto es solo una muestra aproximada y no usa envoltorios para GetCursorPos y SetCursorPos . Usaré los envoltorios del Simulador de entrada de Windows.

static class SampleMouseMove {

    static Random random = new Random();
    static int mouseSpeed = 15;

    static void Main(string[] args) {
        MoveMouse(0, 0, 0, 0);
    }

    static void MoveMouse(int x, int y, int rx, int ry) {
        Point c = new Point();
        GetCursorPos(out c);

        x += random.Next(rx);
        y += random.Next(ry);

        double randomSpeed = Math.Max((random.Next(mouseSpeed) / 2.0 + mouseSpeed) / 10.0, 0.1);

        WindMouse(c.X, c.Y, x, y, 9.0, 3.0, 10.0 / randomSpeed,
            15.0 / randomSpeed, 10.0 * randomSpeed, 10.0 * randomSpeed); 
    }

    static void WindMouse(double xs, double ys, double xe, double ye,
        double gravity, double wind, double minWait, double maxWait,
        double maxStep, double targetArea) {

        double dist, windX = 0, windY = 0, veloX = 0, veloY = 0, randomDist, veloMag, step;
        int oldX, oldY, newX = (int)Math.Round(xs), newY = (int)Math.Round(ys);

        double waitDiff = maxWait - minWait;
        double sqrt2 = Math.Sqrt(2.0);
        double sqrt3 = Math.Sqrt(3.0);
        double sqrt5 = Math.Sqrt(5.0);

        dist = Hypot(xe - xs, ye - ys);

        while (dist > 1.0) {

            wind = Math.Min(wind, dist);

            if (dist >= targetArea) {
                int w = random.Next((int)Math.Round(wind) * 2 + 1);
                windX = windX / sqrt3 + (w - wind) / sqrt5;
                windY = windY / sqrt3 + (w - wind) / sqrt5;
            }
            else {
                windX = windX / sqrt2;
                windY = windY / sqrt2;
                if (maxStep < 3)
                    maxStep = random.Next(3) + 3.0;
                else
                    maxStep = maxStep / sqrt5;
            }

            veloX += windX;
            veloY += windY;
            veloX = veloX + gravity * (xe - xs) / dist;
            veloY = veloY + gravity * (ye - ys) / dist;

            if (Hypot(veloX, veloY) > maxStep) {
                randomDist = maxStep / 2.0 + random.Next((int)Math.Round(maxStep) / 2);
                veloMag = Hypot(veloX, veloY);
                veloX = (veloX / veloMag) * randomDist;
                veloY = (veloY / veloMag) * randomDist;
            }

            oldX = (int)Math.Round(xs);
            oldY = (int)Math.Round(ys);
            xs += veloX;
            ys += veloY;
            dist = Hypot(xe - xs, ye - ys);
            newX = (int)Math.Round(xs);
            newY = (int)Math.Round(ys);

            if (oldX != newX || oldY != newY)
                SetCursorPos(newX, newY);

            step = Hypot(xs - oldX, ys - oldY);
            int wait = (int)Math.Round(waitDiff * (step / maxStep) + minWait);
            Thread.Sleep(wait);
        }

        int endX = (int)Math.Round(xe);
        int endY = (int)Math.Round(ye);
        if (endX != newX || endY != newY)
            SetCursorPos(endX, endY);
    }

    static double Hypot(double dx, double dy) {
        return Math.Sqrt(dx * dx + dy * dy);
    }

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

    [DllImport("user32.dll")]
    public static extern bool GetCursorPos(out Point p);
}

procedure WindMouse(xs, ys, xe, ye, gravity, wind, minWait, maxWait, maxStep, targetArea: extended);
var
  veloX, veloY, windX, windY, veloMag, dist, randomDist, lastDist, step: extended;
  lastX, lastY: integer;
  sqrt2, sqrt3, sqrt5: extended;
begin
  sqrt2:= sqrt(2);
  sqrt3:= sqrt(3);
  sqrt5:= sqrt(5);
  while hypot(xs - xe, ys - ye) > 1 do
  begin
    dist:= hypot(xs - xe, ys - ye);
    wind:= minE(wind, dist);
    if dist >= targetArea then
    begin
      windX:= windX / sqrt3 + (random(round(wind) * 2 + 1) - wind) / sqrt5;
      windY:= windY / sqrt3 + (random(round(wind) * 2 + 1) - wind) / sqrt5;
    end else
    begin
      windX:= windX / sqrt2;
      windY:= windY / sqrt2;
      if (maxStep < 3) then
      begin
        maxStep:= random(3) + 3.0;
      end else
      begin
        maxStep:= maxStep / sqrt5;
      end;
    end;
    veloX:= veloX + windX;
    veloY:= veloY + windY;
    veloX:= veloX + gravity * (xe - xs) / dist;
    veloY:= veloY + gravity * (ye - ys) / dist;
    if hypot(veloX, veloY) > maxStep then
    begin
      randomDist:= maxStep / 2.0 + random(round(maxStep) / 2);
      veloMag:= sqrt(veloX * veloX + veloY * veloY);
      veloX:= (veloX / veloMag) * randomDist;
      veloY:= (veloY / veloMag) * randomDist;
    end;
    lastX:= Round(xs);
    lastY:= Round(ys);
    xs:= xs + veloX;
    ys:= ys + veloY;
    if (lastX <> Round(xs)) or (lastY <> Round(ys)) then
      MoveMouse(Round(xs), Round(ys));
    step:= hypot(xs - lastX, ys - lastY);
    wait(round((maxWait - minWait) * (step / maxStep) + minWait));
    lastdist:= dist;
  end;
  if (Round(xe) <> Round(xs)) or (Round(ye) <> Round(ys)) then
    MoveMouse(Round(xe), Round(ye));
end;

{*******************************************************************************
procedure MMouse(x, y, rx, ry: integer);
By: Benland100
Description: Moves the mouse.
*******************************************************************************}
//Randomness is just added to the x,y. Might want to change that.
procedure MMouse(x, y, rx, ry: integer);
var
  cx, cy: integer;
  randSpeed: extended;
begin
  randSpeed:= (random(MouseSpeed) / 2.0 + MouseSpeed) / 10.0;
  if randSpeed = 0.0 then
    randSpeed := 0.1;
  getMousePos(cx,cy);
  X := x + random(rx);
  Y := y + random(ry);
  WindMouse(cx,cy,x,y,9.0,3.0,10.0/randSpeed,15.0/randSpeed,10.0*randSpeed,10.0*randSpeed);
end;

Aquí hay algunos métodos escritos en SCAR. Convertirlos en C# no debería ser demasiado difícil, estos son bastante realistas.