Płynny ruch kursora

0

Szukam jakiejś gotowej funkcji (jeśli taka istnieje?), której wywołanie z przekazanymi parametrami przez wartość jednostajnie przesunie kursor z p1 = (x1, y1) do p2 = (x2, y2) w określonym czasie.

Korzystając z funkcji WINAPI SetCursorPos(int,int) zrobiłem:

#include <iostream>
#include <windows.h>

short MoveCursor(short x1, short y1, short x2, short y2, short delay)
{
    SetCursorPos(x1, y1); // initial cursor position
    Sleep(delay);
    SetCursorPos(x2, y2); // final cursor position
}

int main()
{
    MoveCursor(200, 200, 1000, 1000, 2000);
}

ale to od razu przesuwa kursor w daną pozycję.
Wpadłem na głupi pomysł żeby napisać funkcję, która będzie w zapętleniu przesuwać kursor o 1px aż do momentu gdy osiągnie swoją finalną pozycję (warning, ugly code below):

#include <windows.h>

short SmoothCursor(short x1, short y1, short x2, short y2, short delay)
{
    double X_PixelHopDelay = delay / abs(x2 - x1);
    double Y_PixelHopDelay = delay / abs(y2 - y1);
    double avg_PixelHopDelay = (X_PixelHopDelay + Y_PixelHopDelay) / 2;

    SetCursorPos(x1, y1); // initial cursor position
    if (x1 <= x2 && y1 <= y2) {
        while (x1 <= x2 && y1 <= y2) {
            Sleep(avg_PixelHopDelay);
            SetCursorPos(x1++, y1++);
        }
    }
    else if (x1 >= x2 && y1 <= y2) {
        while (x1 >= x2 && y1 <= y2) {
            Sleep(avg_PixelHopDelay);
            SetCursorPos(x1--, y1++);
        }
    }
    else if (x1 >= x2 && y1 >= y2) {
        while (x1 >= x2 && y1 >= y2) {
            Sleep(avg_PixelHopDelay);
            SetCursorPos(x1--, y1--);
        }
    }
    else if (x1 <= x2 && y1 >= y2) {
        while (x1 <= x2 && y1 >= y2) {
            Sleep(avg_PixelHopDelay);
            SetCursorPos(x1++, y1--);
        }
    }
}

int main()
{
    SmoothCursor(200, 600, 1000, 200, 1600);
}

To daje mi prawie zamierzony efekt, ale tylko jeśli przesunięcie po osi X = przesunięcie po osi Y.

SmoothCursor(200, 200, 1000, 1000, 1600); // dobry rezultat - wykonuje się w 1600ms*
SmoothCursor(200, 800, 1000, 1000, 1600); // zły rezultat - przesunięcie po osi X to 800px, a po osi Y to 200px
// całość wykonuje się szybciej niż w 1600ms

Powodem jest pewnie:

    double X_PixelHopDelay = delay / abs(x2 - x1);
    double Y_PixelHopDelay = delay / abs(y2 - y1);
    double avg_PixelHopDelay = (X_PixelHopDelay + Y_PixelHopDelay) / 2;

ale w jakiś sposób przecież muszę określać co ile milisekund ma się kursor przesuwać.

  1. Jest może jakaś gotowa biblioteka/funkcja która wydajniej przesuwałaby kursor?
    1.1. Jeśli nie, w jaki sposób mogę rozwiązać problem jeśli przesunięcie x1->x2 =/= przesunięcie y1->y2?
    1.2. Z tego co wiem Windows nie obsłuży niczego poniżej 1ms. Wykonanie się pętli 1000x: Sleep(1); na moim PC trwa około ~2 sekundy. Możecie zaproponować coś wydajniejszego i precyzyjniejszego od Sleep, ale jeśli to możliwe to łatwego do ogarnięcia dla nooba?

Dziękuję ;-)

1

Dla ludzkiego oka płynny ruch zaczyna się przy 15 fps, czyli przy ~66ms między klatkami. Jak będziesz robił 30 lub 60 zmian na sekundę to i tak będziesz widział płynny ruch, nie potrzeba tu tysiąca.

Dla obu wymiarów licz przesunięcie osobno, i zamiast przesuwać sztywno, sprawdzaj ile czasu minęło od ostatniego wywołania i ustaw kursor tam, gdzie właśnie powinien być.

1 użytkowników online, w tym zalogowanych: 0, gości: 1